From 46e7c30a718f41607521274c7f4500fa9a1afa76 Mon Sep 17 00:00:00 2001 From: Oliver Stieber Date: Thu, 23 Jun 2005 11:05:24 +0000 Subject: [PATCH] Implement swapchains. --- dlls/d3d8/d3d8_private.h | 3 + dlls/d3d8/directx.c | 57 +++- dlls/d3d9/d3d9_private.h | 36 +-- dlls/d3d9/device.c | 1 - dlls/d3d9/directx.c | 133 ++++++-- dlls/d3d9/swapchain.c | 118 ++++++-- dlls/wined3d/Makefile.in | 1 + dlls/wined3d/device.c | 633 +++++++++++++++++++++++++++++++-------- dlls/wined3d/directx.c | 308 +++++-------------- dlls/wined3d/swapchain.c | 458 ++++++++++++++++++++++++++++ dlls/wined3d/wined3d_private.h | 54 +++- include/wine/wined3d_interface.h | 59 +++- 12 files changed, 1400 insertions(+), 461 deletions(-) create mode 100644 dlls/wined3d/swapchain.c diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h index fa65f21fc74..c1ec0bb097f 100644 --- a/dlls/d3d8/d3d8_private.h +++ b/dlls/d3d8/d3d8_private.h @@ -655,6 +655,9 @@ struct IDirect3DSwapChain8Impl /* OpenGL/GLX related */ GLXContext swap_ctx; Drawable swap_drawable; + + /* ready for when we move over to wined3d */ + IWineD3DSwapChain *wineD3DSwapChain; }; /* IUnknown: */ diff --git a/dlls/d3d8/directx.c b/dlls/d3d8/directx.c index ae3996a9592..ecf2ca4d40f 100644 --- a/dlls/d3d8/directx.c +++ b/dlls/d3d8/directx.c @@ -579,6 +579,61 @@ HRESULT WINAPI D3D8CB_CreateRenderTarget(IUnknown *device, UINT Width, UINT Heig return res; } +/* Callback for creating the inplicite swapchain when the device is created */ +HRESULT WINAPI D3D8CB_CreateAdditionalSwapChain(IUnknown *device, + WINED3DPRESENT_PARAMETERS* pPresentationParameters, + IWineD3DSwapChain ** ppSwapChain){ + HRESULT res = D3D_OK; + IDirect3DSwapChain8Impl *d3dSwapChain = NULL; + /* We have to pass the presentation parameters back and forth */ + D3DPRESENT_PARAMETERS localParameters; + localParameters.BackBufferWidth = *(pPresentationParameters->BackBufferWidth); + localParameters.BackBufferHeight = *(pPresentationParameters->BackBufferHeight); + localParameters.BackBufferFormat = *(pPresentationParameters->BackBufferFormat); + localParameters.BackBufferCount = *(pPresentationParameters->BackBufferCount); + localParameters.MultiSampleType = *(pPresentationParameters->MultiSampleType); + /* d3d9 only */ + /* localParameters.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality); */ + localParameters.SwapEffect = *(pPresentationParameters->SwapEffect); + localParameters.hDeviceWindow = *(pPresentationParameters->hDeviceWindow); + localParameters.Windowed = *(pPresentationParameters->Windowed); + localParameters.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil); + localParameters.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat); + localParameters.Flags = *(pPresentationParameters->Flags); + localParameters.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz); +/* not in d3d8 */ +/* localParameters.PresentationInterval = *(pPresentationParameters->PresentationInterval); */ + + TRACE("(%p) rellaying\n", device); + /*copy the presentation parameters*/ + res = IDirect3DDevice8_CreateAdditionalSwapChain((IDirect3DDevice8 *)device, &localParameters, (IDirect3DSwapChain8 **)&d3dSwapChain); + + if (res == D3D_OK){ + *ppSwapChain = d3dSwapChain->wineD3DSwapChain; + } else { + FIXME("failed to create additional swap chain\n"); + *ppSwapChain = NULL; + } + /* Copy back the presentation parameters */ + TRACE("(%p) setting up return parameters\n", device); + *pPresentationParameters->BackBufferWidth = localParameters.BackBufferWidth; + *pPresentationParameters->BackBufferHeight = localParameters.BackBufferHeight; + *pPresentationParameters->BackBufferFormat = localParameters.BackBufferFormat; + *pPresentationParameters->BackBufferCount = localParameters.BackBufferCount; + *pPresentationParameters->MultiSampleType = localParameters.MultiSampleType; +/* *pPresentationParameters->MultiSampleQuality leave alone incase wineD3D set something internally */ + *pPresentationParameters->SwapEffect = localParameters.SwapEffect; + *pPresentationParameters->hDeviceWindow = localParameters.hDeviceWindow; + *pPresentationParameters->Windowed = localParameters.Windowed; + *pPresentationParameters->EnableAutoDepthStencil = localParameters.EnableAutoDepthStencil; + *pPresentationParameters->AutoDepthStencilFormat = localParameters.AutoDepthStencilFormat; + *pPresentationParameters->Flags = localParameters.Flags; + *pPresentationParameters->FullScreen_RefreshRateInHz = localParameters.FullScreen_RefreshRateInHz; +/* *pPresentationParameters->PresentationInterval leave alone incase wineD3D set something internally */ + + return res; +} + HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, @@ -624,7 +679,7 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface, localParameters.Flags = &pPresentationParameters->Flags; localParameters.FullScreen_RefreshRateInHz = &pPresentationParameters->FullScreen_RefreshRateInHz; localParameters.PresentationInterval = &pPresentationParameters->FullScreen_PresentationInterval; /* Renamed in dx9 */ - IWineD3D_CreateDevice(This->WineD3D, Adapter, DeviceType, hFocusWindow, BehaviourFlags, &localParameters, &object->WineD3DDevice, (IUnknown *)object, D3D8CB_CreateRenderTarget); + IWineD3D_CreateDevice(This->WineD3D, Adapter, DeviceType, hFocusWindow, BehaviourFlags, &localParameters, &object->WineD3DDevice, (IUnknown *)object, D3D8CB_CreateAdditionalSwapChain); /** use StateBlock Factory here, for creating the startup stateBlock */ object->StateBlock = NULL; diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h index b0aedf5709e..4c96a63c938 100644 --- a/dlls/d3d9/d3d9_private.h +++ b/dlls/d3d9/d3d9_private.h @@ -184,7 +184,6 @@ typedef struct IDirect3DCubeTexture9Impl IDirect3DCubeTexture9Impl; typedef struct IDirect3DVertexBuffer9Impl IDirect3DVertexBuffer9Impl; typedef struct IDirect3DIndexBuffer9Impl IDirect3DIndexBuffer9Impl; typedef struct IDirect3DSurface9Impl IDirect3DSurface9Impl; -typedef struct IDirect3DSwapChain9Impl IDirect3DSwapChain9Impl; typedef struct IDirect3DResource9Impl IDirect3DResource9Impl; typedef struct IDirect3DVolume9Impl IDirect3DVolume9Impl; typedef struct IDirect3DStateBlock9Impl IDirect3DStateBlock9Impl; @@ -560,34 +559,15 @@ extern const IDirect3DSwapChain9Vtbl Direct3DSwapChain9_Vtbl; /***************************************************************************** * IDirect3DSwapChain9 implementation structure */ -struct IDirect3DSwapChain9Impl +typedef struct IDirect3DSwapChain9Impl { /* IUnknown fields */ const IDirect3DSwapChain9Vtbl *lpVtbl; DWORD ref; /* IDirect3DSwapChain9 fields */ - IDirect3DDevice9Impl *Device; - IDirect3DSurface9Impl *frontBuffer; - IDirect3DSurface9Impl *backBuffer; - IDirect3DSurface9Impl *depthStencilBuffer; - D3DPRESENT_PARAMETERS PresentParms; -}; - -/* IUnknown: */ -extern HRESULT WINAPI IDirect3DSwapChain9Impl_QueryInterface(LPDIRECT3DSWAPCHAIN9 iface, REFIID refiid, LPVOID* obj); -extern ULONG WINAPI IDirect3DSwapChain9Impl_AddRef(LPDIRECT3DSWAPCHAIN9 iface); -extern ULONG WINAPI IDirect3DSwapChain9Impl_Release(LPDIRECT3DSWAPCHAIN9 iface); - -/* IDirect3DSwapChain9: */ -extern HRESULT WINAPI IDirect3DSwapChain9Impl_Present(LPDIRECT3DSWAPCHAIN9 iface, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion, DWORD dwFlags); -extern HRESULT WINAPI IDirect3DSwapChain9Impl_GetFrontBufferData(LPDIRECT3DSWAPCHAIN9 iface, IDirect3DSurface9* pDestSurface); -extern HRESULT WINAPI IDirect3DSwapChain9Impl_GetBackBuffer(LPDIRECT3DSWAPCHAIN9 iface, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer); -extern HRESULT WINAPI IDirect3DSwapChain9Impl_GetRasterStatus(LPDIRECT3DSWAPCHAIN9 iface, D3DRASTER_STATUS* pRasterStatus); -extern HRESULT WINAPI IDirect3DSwapChain9Impl_GetDisplayMode(LPDIRECT3DSWAPCHAIN9 iface, D3DDISPLAYMODE* pMode); -extern HRESULT WINAPI IDirect3DSwapChain9Impl_GetDevice(LPDIRECT3DSWAPCHAIN9 iface, IDirect3DDevice9** ppDevice); -extern HRESULT WINAPI IDirect3DSwapChain9Impl_GetPresentParameters(LPDIRECT3DSWAPCHAIN9 iface, D3DPRESENT_PARAMETERS* pPresentationParameters); - + IWineD3DSwapChain *wineD3DSwapChain; +} IDirect3DSwapChain9Impl; /* ------------------ */ /* IDirect3DResource9 */ @@ -1210,4 +1190,14 @@ extern HRESULT WINAPI D3D9CB_CreateVolume(IUnknown *pDevice, UINT Width, UINT H IWineD3DVolume **ppVolume, HANDLE * pSharedHandle); +extern HRESULT WINAPI D3D9CB_CreateDepthStencilSurface(IUnknown *device, UINT Width, UINT Height, + WINED3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, BOOL Discard, + IWineD3DSurface** ppSurface, HANDLE* pSharedHandle); + +extern HRESULT WINAPI D3D9CB_CreateRenderTarget(IUnknown *device, UINT Width, UINT Height, + WINED3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, BOOL Lockable, + IWineD3DSurface** ppSurface, HANDLE* pSharedHandle); + #endif /* __WINE_D3D9_PRIVATE_H */ diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 2d992080a29..8a08a5d4de8 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -57,7 +57,6 @@ ULONG WINAPI IDirect3DDevice9Impl_Release(LPDIRECT3DDEVICE9 iface) { TRACE("(%p) : ReleaseRef to %ld\n", This, ref); if (ref == 0) { - IDirect3D9_Release((LPDIRECT3D9) This->direct3d); IWineD3DDevice_Release(This->WineD3DDevice); HeapFree(GetProcessHeap(), 0, This); } diff --git a/dlls/d3d9/directx.c b/dlls/d3d9/directx.c index 5ce74f69066..4c7aa853769 100644 --- a/dlls/d3d9/directx.c +++ b/dlls/d3d9/directx.c @@ -175,38 +175,103 @@ HMONITOR WINAPI IDirect3D9Impl_GetAdapterMonitor(LPDIRECT3D9 iface, UINT Adapte } /* Internal function called back during the CreateDevice to create a render target */ -HRESULT WINAPI D3D9CB_CreateRenderTarget(IUnknown *device, UINT Width, UINT Height, - WINED3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, BOOL Lockable, +HRESULT WINAPI D3D9CB_CreateRenderTarget(IUnknown *device, UINT Width, UINT Height, + WINED3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, BOOL Lockable, IWineD3DSurface** ppSurface, HANDLE* pSharedHandle) { HRESULT res = D3D_OK; IDirect3DSurface9Impl *d3dSurface = NULL; - IDirect3DDevice9Impl* pDeviceImpl = (IDirect3DDevice9Impl*) device; - + TRACE("(%p) call back\n", device); res = IDirect3DDevice9_CreateRenderTarget((IDirect3DDevice9 *)device, Width, Height, - (D3DFORMAT) Format, MultiSample, MultisampleQuality, Lockable, + (D3DFORMAT)Format, MultiSample, MultisampleQuality, Lockable, (IDirect3DSurface9 **)&d3dSurface, pSharedHandle); if (SUCCEEDED(res)) { *ppSurface = d3dSurface->wineD3DSurface; - if (NULL == pDeviceImpl->backBuffer) { - pDeviceImpl->backBuffer = d3dSurface; - pDeviceImpl->renderTarget = d3dSurface; - IDirect3DSurface9Impl_AddRef((LPDIRECT3DSURFACE9) pDeviceImpl->renderTarget); - } } else { *ppSurface = NULL; } return res; } +HRESULT WINAPI D3D9CB_CreateAdditionalSwapChain(IUnknown *device, + WINED3DPRESENT_PARAMETERS* pPresentationParameters, + IWineD3DSwapChain ** ppSwapChain) { + HRESULT res = D3D_OK; + IDirect3DSwapChain9Impl *d3dSwapChain = NULL; + D3DPRESENT_PARAMETERS localParameters; + TRACE("(%p) call back\n", device); + + localParameters.BackBufferWidth = *(pPresentationParameters->BackBufferWidth); + localParameters.BackBufferHeight = *(pPresentationParameters->BackBufferHeight); + localParameters.BackBufferFormat = *(pPresentationParameters->BackBufferFormat); + localParameters.BackBufferCount = *(pPresentationParameters->BackBufferCount); + localParameters.MultiSampleType = *(pPresentationParameters->MultiSampleType); + localParameters.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality); + localParameters.SwapEffect = *(pPresentationParameters->SwapEffect); + localParameters.hDeviceWindow = *(pPresentationParameters->hDeviceWindow); + localParameters.Windowed = *(pPresentationParameters->Windowed); + localParameters.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil); + localParameters.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat); + localParameters.Flags = *(pPresentationParameters->Flags); + localParameters.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz); + localParameters.PresentationInterval = *(pPresentationParameters->PresentationInterval); + + /*copy the presentation parameters*/ + res = IDirect3DDevice9_CreateAdditionalSwapChain((IDirect3DDevice9 *)device, &localParameters, (IDirect3DSwapChain9 **)&d3dSwapChain); + + if (res == D3D_OK && d3dSwapChain != NULL) { + *ppSwapChain = d3dSwapChain->wineD3DSwapChain; + } else { + *ppSwapChain = NULL; + } + /*Copy back the presentation parameters*/ + *pPresentationParameters->BackBufferWidth = localParameters.BackBufferWidth; + *pPresentationParameters->BackBufferHeight = localParameters.BackBufferHeight; + *pPresentationParameters->BackBufferFormat = localParameters.BackBufferFormat; + *pPresentationParameters->BackBufferCount = localParameters.BackBufferCount; + *pPresentationParameters->MultiSampleType = localParameters.MultiSampleType; + *pPresentationParameters->MultiSampleQuality = localParameters.MultiSampleQuality; + *pPresentationParameters->SwapEffect = localParameters.SwapEffect; + *pPresentationParameters->hDeviceWindow = localParameters.hDeviceWindow; + *pPresentationParameters->Windowed = localParameters.Windowed; + *pPresentationParameters->EnableAutoDepthStencil = localParameters.EnableAutoDepthStencil; + *pPresentationParameters->AutoDepthStencilFormat = localParameters.AutoDepthStencilFormat; + *pPresentationParameters->Flags = localParameters.Flags; + *pPresentationParameters->FullScreen_RefreshRateInHz = localParameters.FullScreen_RefreshRateInHz; + *pPresentationParameters->PresentationInterval = localParameters.PresentationInterval; + + return res; +} + +/* Internal function called back during the CreateDevice to create a render target */ +HRESULT WINAPI D3D9CB_CreateDepthStencilSurface(IUnknown *device, UINT Width, UINT Height, + WINED3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, BOOL Discard, + IWineD3DSurface** ppSurface, HANDLE* pSharedHandle) { + HRESULT res = D3D_OK; + IDirect3DSurface9Impl *d3dSurface = NULL; + TRACE("(%p) call back\n", device); + + res = IDirect3DDevice9_CreateDepthStencilSurface((IDirect3DDevice9 *)device, Width, Height, + (D3DFORMAT)Format, MultiSample, MultisampleQuality, Discard, + (IDirect3DSurface9 **)&d3dSurface, pSharedHandle); + if (res == D3D_OK) { + *ppSurface = d3dSurface->wineD3DSurface; + } + return res; +} + + HRESULT WINAPI IDirect3D9Impl_CreateDevice(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, - DWORD BehaviourFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, - IDirect3DDevice9** ppReturnedDeviceInterface) { + DWORD BehaviourFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, + IDirect3DDevice9** ppReturnedDeviceInterface) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; IDirect3DDevice9Impl *object = NULL; WINED3DPRESENT_PARAMETERS localParameters; + HRESULT hr; + TRACE("(%p) Relay \n", This); /* Check the validity range of the adapter parameter */ if (Adapter >= IDirect3D9Impl_GetAdapterCount(iface)) { @@ -224,28 +289,38 @@ HRESULT WINAPI IDirect3D9Impl_CreateDevice(LPDIRECT3D9 iface, UINT Adapter, D3 object->lpVtbl = &Direct3DDevice9_Vtbl; object->ref = 1; - object->direct3d = This; - IDirect3D9_AddRef((LPDIRECT3D9) object->direct3d); *ppReturnedDeviceInterface = (IDirect3DDevice9 *)object; - + /* Allocate an associated WineD3DDevice object */ localParameters.BackBufferWidth = &pPresentationParameters->BackBufferWidth; - localParameters.BackBufferHeight = &pPresentationParameters->BackBufferHeight; - localParameters.BackBufferFormat = &pPresentationParameters->BackBufferFormat; - localParameters.BackBufferCount = &pPresentationParameters->BackBufferCount; - localParameters.MultiSampleType = &pPresentationParameters->MultiSampleType; - localParameters.MultiSampleQuality = &pPresentationParameters->MultiSampleQuality; - localParameters.SwapEffect = &pPresentationParameters->SwapEffect; - localParameters.hDeviceWindow = &pPresentationParameters->hDeviceWindow; - localParameters.Windowed = &pPresentationParameters->Windowed; - localParameters.EnableAutoDepthStencil = &pPresentationParameters->EnableAutoDepthStencil; - localParameters.AutoDepthStencilFormat = &pPresentationParameters->AutoDepthStencilFormat; - localParameters.Flags = &pPresentationParameters->Flags; + localParameters.BackBufferHeight = &pPresentationParameters->BackBufferHeight; + localParameters.BackBufferFormat = &pPresentationParameters->BackBufferFormat; + localParameters.BackBufferCount = &pPresentationParameters->BackBufferCount; + localParameters.MultiSampleType = &pPresentationParameters->MultiSampleType; + localParameters.MultiSampleQuality = &pPresentationParameters->MultiSampleQuality; + localParameters.SwapEffect = &pPresentationParameters->SwapEffect; + localParameters.hDeviceWindow = &pPresentationParameters->hDeviceWindow; + localParameters.Windowed = &pPresentationParameters->Windowed; + localParameters.EnableAutoDepthStencil = &pPresentationParameters->EnableAutoDepthStencil; + localParameters.AutoDepthStencilFormat = &pPresentationParameters->AutoDepthStencilFormat; + localParameters.Flags = &pPresentationParameters->Flags; localParameters.FullScreen_RefreshRateInHz = &pPresentationParameters->FullScreen_RefreshRateInHz; - localParameters.PresentationInterval = &pPresentationParameters->PresentationInterval; - return IWineD3D_CreateDevice(This->WineD3D, Adapter, DeviceType, hFocusWindow, BehaviourFlags, &localParameters, &object->WineD3DDevice, (IUnknown *)object, D3D9CB_CreateRenderTarget); + localParameters.PresentationInterval = &pPresentationParameters->PresentationInterval; + + hr =IWineD3D_CreateDevice(This->WineD3D, Adapter, DeviceType, hFocusWindow, BehaviourFlags, &localParameters, &object->WineD3DDevice, (IUnknown *)object, D3D9CB_CreateAdditionalSwapChain); + + if (hr == D3D_OK) { + + TRACE("(%p) : Created Device %p\n", This, object); + } else { + HeapFree(GetProcessHeap(), 0, object); + *ppReturnedDeviceInterface = NULL; + } + return hr; } + + const IDirect3D9Vtbl Direct3D9_Vtbl = { IDirect3D9Impl_QueryInterface, diff --git a/dlls/d3d9/swapchain.c b/dlls/d3d9/swapchain.c index 93ce2914825..dbe23d1b172 100644 --- a/dlls/d3d9/swapchain.c +++ b/dlls/d3d9/swapchain.c @@ -3,6 +3,7 @@ * * Copyright 2002-2003 Jason Edmeades * Raphael Junqueira + * Copyright 2005 Oliver Stieber * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,7 +23,7 @@ #include "config.h" #include "d3d9_private.h" -WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DEFAULT_DEBUG_CHANNEL(d3d9); /* IDirect3DSwapChain IUnknown parts follow: */ HRESULT WINAPI IDirect3DSwapChain9Impl_QueryInterface(LPDIRECT3DSWAPCHAIN9 iface, REFIID riid, LPVOID* ppobj) @@ -31,8 +32,8 @@ HRESULT WINAPI IDirect3DSwapChain9Impl_QueryInterface(LPDIRECT3DSWAPCHAIN9 iface if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDirect3DSwapChain9)) { - IDirect3DSwapChain9Impl_AddRef(iface); - *ppobj = This; + IUnknown_AddRef(iface); + *ppobj = This; return D3D_OK; } @@ -64,50 +65,62 @@ ULONG WINAPI IDirect3DSwapChain9Impl_Release(LPDIRECT3DSWAPCHAIN9 iface) { /* IDirect3DSwapChain9 parts follow: */ HRESULT WINAPI IDirect3DSwapChain9Impl_Present(LPDIRECT3DSWAPCHAIN9 iface, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion, DWORD dwFlags) { IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n", This); + return IWineD3DSwapChain_Present(This->wineD3DSwapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags); } HRESULT WINAPI IDirect3DSwapChain9Impl_GetFrontBufferData(LPDIRECT3DSWAPCHAIN9 iface, IDirect3DSurface9* pDestSurface) { IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n", This); + return IWineD3DSwapChain_GetFrontBufferData(This->wineD3DSwapChain, ((IDirect3DSurface9Impl *)pDestSurface)->wineD3DSurface); } HRESULT WINAPI IDirect3DSwapChain9Impl_GetBackBuffer(LPDIRECT3DSWAPCHAIN9 iface, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) { IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + HRESULT hrc = D3D_OK; + IWineD3DSurface *mySurface = NULL; + + TRACE("(%p) Relay\n", This); + + hrc = IWineD3DSwapChain_GetBackBuffer(This->wineD3DSwapChain, iBackBuffer, Type, &mySurface); + if (hrc == D3D_OK && NULL != mySurface) { + IWineD3DSurface_GetParent(mySurface, (IUnknown **)ppBackBuffer); + IWineD3DSurface_Release(mySurface); + } + return hrc; } HRESULT WINAPI IDirect3DSwapChain9Impl_GetRasterStatus(LPDIRECT3DSWAPCHAIN9 iface, D3DRASTER_STATUS* pRasterStatus) { IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n", This); + return IWineD3DSwapChain_GetRasterStatus(This->wineD3DSwapChain, pRasterStatus); } HRESULT WINAPI IDirect3DSwapChain9Impl_GetDisplayMode(LPDIRECT3DSWAPCHAIN9 iface, D3DDISPLAYMODE* pMode) { IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n", This); + return IWineD3DSwapChain_GetDisplayMode(This->wineD3DSwapChain, pMode); } HRESULT WINAPI IDirect3DSwapChain9Impl_GetDevice(LPDIRECT3DSWAPCHAIN9 iface, IDirect3DDevice9** ppDevice) { - IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface; - TRACE("(%p) : returning %p\n", This, This->Device); - *ppDevice = (LPDIRECT3DDEVICE9) This->Device; + IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface; + HRESULT hrc = D3D_OK; + IWineD3DDevice *device = NULL; - /* Note Calling this method will increase the internal reference count - on the IDirect3DDevice9 interface. */ - IDirect3DDevice9Impl_AddRef(*ppDevice); - return D3D_OK; + TRACE("(%p) Relay\n", This); + + hrc = IWineD3DSwapChain_GetDevice(This->wineD3DSwapChain, &device); + if (hrc == D3D_OK && NULL != device) { + IWineD3DDevice_GetParent(device, (IUnknown **)ppDevice); + IWineD3DDevice_Release(device); + } + return hrc; } HRESULT WINAPI IDirect3DSwapChain9Impl_GetPresentParameters(LPDIRECT3DSWAPCHAIN9 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) { IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface; - FIXME("(%p) : copy\n", This); - memcpy(pPresentationParameters, &This->PresentParms, sizeof(D3DPRESENT_PARAMETERS)); - return D3D_OK; + FIXME("(%p) : inplement using WINED3DPRESENT_PARAMERS\n", This); + return IWineD3DSwapChain_GetPresentParameters(This->wineD3DSwapChain, pPresentationParameters); } @@ -129,18 +142,67 @@ const IDirect3DSwapChain9Vtbl Direct3DSwapChain9_Vtbl = /* IDirect3DDevice9 IDirect3DSwapChain9 Methods follow: */ HRESULT WINAPI IDirect3DDevice9Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE9 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain9** pSwapChain) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); + IDirect3DSwapChain9Impl* object; + HRESULT hrc = D3D_OK; + WINED3DPRESENT_PARAMETERS localParameters; + + TRACE("(%p) Relay\n", This); + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (NULL == object) { + FIXME("Allocation of memory failed\n"); + *pSwapChain = NULL; + return D3DERR_OUTOFVIDEOMEMORY; + } + object->ref = 1; + object->lpVtbl = &Direct3DSwapChain9_Vtbl; + + /* Allocate an associated WineD3DDevice object */ + localParameters.BackBufferWidth = &pPresentationParameters->BackBufferWidth; + localParameters.BackBufferHeight = &pPresentationParameters->BackBufferHeight; + localParameters.BackBufferFormat = &pPresentationParameters->BackBufferFormat; + localParameters.BackBufferCount = &pPresentationParameters->BackBufferCount; + localParameters.MultiSampleType = &pPresentationParameters->MultiSampleType; + localParameters.MultiSampleQuality = &pPresentationParameters->MultiSampleQuality; + localParameters.SwapEffect = &pPresentationParameters->SwapEffect; + localParameters.hDeviceWindow = &pPresentationParameters->hDeviceWindow; + localParameters.Windowed = &pPresentationParameters->Windowed; + localParameters.EnableAutoDepthStencil = &pPresentationParameters->EnableAutoDepthStencil; + localParameters.AutoDepthStencilFormat = &pPresentationParameters->AutoDepthStencilFormat; + localParameters.Flags = &pPresentationParameters->Flags; + localParameters.FullScreen_RefreshRateInHz = &pPresentationParameters->FullScreen_RefreshRateInHz; + localParameters.PresentationInterval = &pPresentationParameters->PresentationInterval; + + + hrc = IWineD3DDevice_CreateAdditionalSwapChain(This->WineD3DDevice, &localParameters, &object->wineD3DSwapChain, (IUnknown*)object, D3D9CB_CreateRenderTarget, D3D9CB_CreateDepthStencilSurface); + if (hrc != D3D_OK) { + FIXME("(%p) call to IWineD3DDevice_CreateAdditionalSwapChain failed\n", This); + HeapFree(GetProcessHeap(), 0 , object); + *pSwapChain = NULL; + }else{ + *pSwapChain = (IDirect3DSwapChain9 *)object; + } + TRACE("(%p) returning %p\n", This, *pSwapChain); return D3D_OK; } HRESULT WINAPI IDirect3DDevice9Impl_GetSwapChain(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, IDirect3DSwapChain9** pSwapChain) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + HRESULT hrc = D3D_OK; + IWineD3DSwapChain *swapchain = NULL; + + TRACE("(%p) Relay\n", This); + + hrc = IWineD3DDevice_GetSwapChain(This->WineD3DDevice, iSwapChain, &swapchain); + if (hrc == D3D_OK && NULL != swapchain) { + IWineD3DSwapChain_GetParent(swapchain, (IUnknown **)pSwapChain); + IWineD3DSwapChain_Release(swapchain); + } + return hrc; } UINT WINAPI IDirect3DDevice9Impl_GetNumberOfSwapChains(LPDIRECT3DDEVICE9 iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return 1; + TRACE("(%p) Relay\n", This); + return IWineD3DDevice_GetNumberOfSwapChains(This->WineD3DDevice); } diff --git a/dlls/wined3d/Makefile.in b/dlls/wined3d/Makefile.in index 6c8e2e73fcb..51bb669ad80 100644 --- a/dlls/wined3d/Makefile.in +++ b/dlls/wined3d/Makefile.in @@ -19,6 +19,7 @@ C_SRCS = \ resource.c \ stateblock.c \ surface.c \ + swapchain.c \ texture.c \ utils.c \ vertexbuffer.c \ diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 7e596702592..da38662c625 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -30,6 +30,26 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_fps); WINE_DECLARE_DEBUG_CHANNEL(d3d_shader); #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info +/* x11drv GDI escapes */ +#define X11DRV_ESCAPE 6789 +enum x11drv_escape_codes +{ + X11DRV_GET_DISPLAY, /* get X11 display for a DC */ + X11DRV_GET_DRAWABLE, /* get current drawable for a DC */ + X11DRV_GET_FONT, /* get current X font for a DC */ +}; + +/* retrieve the X display to use on a given DC */ +inline static Display *get_display( HDC hdc ) +{ + Display *display; + enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY; + + if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, + sizeof(display), (LPSTR)&display )) display = NULL; + return display; +} + /* helper macros */ #define D3DMEMCHECK(object, ppResult) if(NULL == object){ *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;} @@ -275,7 +295,29 @@ ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) { if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/ /* NOTE: You must release the parent if the objects was created via a callback ** ***************************/ - IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock); + int i; + IUnknown* swapChainParent; + + /* Release all of the swapchains, except the implicite swapchain (#0) */ + for(i = 1; i < This->numberOfSwapChains; i++){ + /* TODO: don't access swapchains[x] directly! */ + IWineD3DSwapChain_Release(This->swapchains[i]); + } + + if (This->stateBlock != NULL) { + IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock); + } + + if (This->swapchains[0] != NULL) { + /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release it's parent now */ + /* TODO: don't access swapchains[x] directly!, check that there are no-more swapchains left for this device! */ + IWineD3DSwapChain_GetParent(This->swapchains[0], &swapChainParent); + IUnknown_Release(swapChainParent); /* once for the get parent */ + if (IUnknown_Release(swapChainParent) > 0){ /* the second time for when it was created */ + FIXME("(%p) Something's still holding the implicite swapchain\n",This); + } + } + } IWineD3D_Release(This->wineD3D); HeapFree(GetProcessHeap(), 0, This); @@ -412,11 +454,11 @@ HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Wid while (pow2Width < Width) pow2Width <<= 1; while (pow2Height < Height) pow2Height <<= 1; - if(pow2Width > Width || pow2Height > Height){ - FIXME("non-power-two textures unsupported\n"); /* OpenGL provides support for these gratis */ + if((pow2Width > Width || pow2Height > Height) && !Usage & D3DUSAGE_RENDERTARGET) { + /** TODO: add support for non power two textures (OpenGL 2 provices support for * non-power-two textures gratis) **/ + FIXME("non-power-two textures unsupported\n"); return D3DERR_NOTAVAILABLE; } - /** TODO: Check against the maximum texture sizes supported by the video card **/ @@ -779,28 +821,418 @@ HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUER } /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */ -HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, void** ppSwapChain, +HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain, IUnknown* parent, D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget, D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil){ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - *ppSwapChain = NULL; - FIXME("(%p) : Stub\n",This); - return D3D_OK; + + HDC hDc; + IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/ + int num; + XVisualInfo template; + GLXContext oldContext; + Drawable oldDrawable; + HRESULT hr = D3D_OK; + + TRACE("(%p) : Created Aditional Swap Chain\n", This); + + /** FIXME: Test under windows to find out what the life cycle of a swap chain is, + * does a device hold a reference to a swap chain giving them a lifetime of the device + * or does the swap chain notify the device of it'd destruction. + *******************************/ + + D3DCREATEOBJECTINSTANCE(object, SwapChain) + + /* Initialize other useful values */ + object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */ + + /********************* + * Lookup the window Handle and the relating X window handle + ********************/ + + /* Setup hwnd we are using, plus which display this equates to */ + object->win_handle = *(pPresentationParameters->hDeviceWindow); + if (!object->win_handle) { + object->win_handle = This->createParms.hFocusWindow; + } + + object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" ); + hDc = GetDC(object->win_handle); + object->display = get_display(hDc); + ReleaseDC(object->win_handle, hDc); + TRACE("Using a display of %p %p \n", object->display, hDc); + + if (NULL == object->display || NULL == hDc) { + WARN("Failed to get a display and HDc for Window %p\n", object->win_handle); + return D3DERR_NOTAVAILABLE; + } + + if (object->win == 0) { + WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle); + return D3DERR_NOTAVAILABLE; + } + /** + * Create an opengl context for the display visual + * NOTE: the visual is chosen as the window is created and the glcontext cannot + * use different properties after that point in time. FIXME: How to handle when requested format + * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one + * it chooses is identical to the one already being used! + **********************************/ + + /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/ + ENTER_GL(); + + /* Create a new context for this swapchain */ + template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id"); + /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request + (or the best possible if none is requested) */ + TRACE("Found x visual ID : %ld\n", template.visualid); + + object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num); + if (NULL == object->visInfo) { + ERR("cannot really get XVisual\n"); + LEAVE_GL(); + return D3DERR_NOTAVAILABLE; + } else { + int n, value; + /* Write out some debug info about the visual/s */ + TRACE("Using x visual ID : %ld\n", template.visualid); + TRACE(" visual info: %p\n", object->visInfo); + TRACE(" num items : %d\n", num); + for(n = 0;n < num; n++){ + TRACE("=====item=====: %d\n", n + 1); + TRACE(" visualid : %ld\n", object->visInfo[n].visualid); + TRACE(" screen : %d\n", object->visInfo[n].screen); + TRACE(" depth : %u\n", object->visInfo[n].depth); + TRACE(" class : %d\n", object->visInfo[n].class); + TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask); + TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask); + TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask); + TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size); + TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb); + /* log some extra glx info */ + glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value); + TRACE(" gl_aux_buffers : %d\n", value); + glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value); + TRACE(" gl_buffer_size : %d\n", value); + glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value); + TRACE(" gl_red_size : %d\n", value); + glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value); + TRACE(" gl_green_size : %d\n", value); + glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value); + TRACE(" gl_blue_size : %d\n", value); + glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value); + TRACE(" gl_alpha_size : %d\n", value); + glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value); + TRACE(" gl_depth_size : %d\n", value); + glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value); + TRACE(" gl_stencil_size : %d\n", value); + } + /* Now choose a simila visual ID*/ + } +#ifdef USE_CONTEXT_MANAGER + + /** TODO: use a context mamager **/ +#endif + + { + IWineD3DSwapChain *implSwapChain; + if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) { + /* The first time around we create the context that is shared with all other swapchians and render targets */ + object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE); + TRACE("Creating implicite context for vis %p, hwnd %p\n", object->display, object->visInfo); + } else { + + TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo); + /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */ + /* and create a new context with the implicit swapchains context as the shared context */ + object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE); + IWineD3DSwapChain_Release(implSwapChain); + } + } + + /* Cleanup */ + XFree(object->visInfo); + object->visInfo = NULL; + + if (NULL == object->glCtx) { + ERR("cannot create glxContext\n"); + LEAVE_GL(); + return D3DERR_NOTAVAILABLE; + } + + LEAVE_GL(); + if (object->glCtx == NULL) { + ERR("Error in context creation !\n"); + return D3DERR_INVALIDCALL; + } else { + TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n", + object->win_handle, object->glCtx, object->win, object->visInfo); + } + + /********************* + * Windowed / Fullscreen + *******************/ + + /** + * TODO: MSDNsays that we are only allowed one fullscreen swapchain per device, + * so we should really check to see if their is a fullscreen swapchain already + * I think Windows and X have differnt ideas about fullscreen, does a single head count as full screen? + **************************************/ + + if (!*(pPresentationParameters->Windowed)) { + + DEVMODEW devmode; + HDC hdc; + int bpp = 0; + + /* Get info on the current display setup */ + hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); + bpp = GetDeviceCaps(hdc, BITSPIXEL); + DeleteDC(hdc); + + /* Change the display settings */ + memset(&devmode, 0, sizeof(DEVMODEW)); + devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */ + devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth); + devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight); + MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME); + ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL); + + /* Make popup window */ + SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP); + SetWindowPos(object->win_handle, HWND_TOP, 0, 0, + *(pPresentationParameters->BackBufferWidth), + *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED); + + + } + + + /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero, + * then the corresponding dimension of the client area of the hDeviceWindow + * (or the focus window, if hDeviceWindow is NULL) is taken. + **********************/ + + if (*(pPresentationParameters->Windowed) && + ((*(pPresentationParameters->BackBufferWidth) == 0) || + (*(pPresentationParameters->BackBufferHeight) == 0))) { + + RECT Rect; + GetClientRect(object->win_handle, &Rect); + + if (*(pPresentationParameters->BackBufferWidth) == 0) { + *(pPresentationParameters->BackBufferWidth) = Rect.right; + TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth)); + } + if (*(pPresentationParameters->BackBufferHeight) == 0) { + *(pPresentationParameters->BackBufferHeight) = Rect.bottom; + TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight)); + } + } + + /********************* + * finish off parameter initialization + *******************/ + + /* Put the correct figures in the presentation parameters */ + TRACE("Coppying accross presentaion paraneters\n"); + object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth); + object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight); + object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat); + object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount); + object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType); + object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality); + object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect); + object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow); + object->presentParms.Windowed = *(pPresentationParameters->Windowed); + object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil); + object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat); + object->presentParms.Flags = *(pPresentationParameters->Flags); + object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz); + object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval); + + + /* FIXME: check for any failures */ + /********************* + * Create the back, front and stencil buffers + *******************/ + TRACE("calling rendertarget CB\n"); + hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent, + object->presentParms.BackBufferWidth, + object->presentParms.BackBufferHeight, + object->presentParms.BackBufferFormat, + object->presentParms.MultiSampleType, + object->presentParms.MultiSampleQuality, + TRUE /* Lockable */, + &object->frontBuffer, + NULL /* pShared (always null)*/); + if (object->frontBuffer != NULL) + IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object); + TRACE("calling rendertarget CB\n"); + hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent, + object->presentParms.BackBufferWidth, + object->presentParms.BackBufferHeight, + object->presentParms.BackBufferFormat, + object->presentParms.MultiSampleType, + object->presentParms.MultiSampleQuality, + TRUE /* Lockable */, + &object->backBuffer, + NULL /* pShared (always null)*/); + if (object->backBuffer != NULL) + IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object); + + /* Under directX swapchains share the depth stencil, so only create one depth-stencil */ + if (pPresentationParameters->EnableAutoDepthStencil) { + TRACE("Creating depth stencil buffer\n"); + if (This->depthStencilBuffer == NULL ) { + hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent, + object->presentParms.BackBufferWidth, + object->presentParms.BackBufferHeight, + object->presentParms.AutoDepthStencilFormat, + object->presentParms.MultiSampleType, + object->presentParms.MultiSampleQuality, + FALSE /* FIXME: Discard */, + &This->depthStencilBuffer, + NULL /* pShared (always null)*/ ); + if (This->depthStencilBuffer != NULL) + IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface); + } + + /** TODO: A check on width, height and multisample types + *(since the zbuffer must be at least as large as the render target and have the same multisample parameters) + ****************************/ + object->wantsDepthStencilBuffer = TRUE; + } else { + object->wantsDepthStencilBuffer = FALSE; + } + + TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer); + + + /********************* + * init the default renderTarget management + *******************/ + object->drawable = object->win; + object->render_ctx = object->glCtx; + + if(hr == D3D_OK){ + /********************* + * Setup some defaults and clear down the buffers + *******************/ + ENTER_GL(); + /** save current context and drawable **/ + oldContext = glXGetCurrentContext(); + oldDrawable = glXGetCurrentDrawable(); + + TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win); + if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) { + ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win); + } + checkGLcall("glXMakeCurrent"); + + TRACE("Setting up the screen\n"); + /* Clear the screen */ + glClearColor(0.0, 0.0, 0.0, 0.0); + checkGLcall("glClearColor"); + glClearIndex(0); + glClearDepth(1); + glClearStencil(0xffff); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + checkGLcall("glClear"); + + glColor3f(1.0, 1.0, 1.0); + checkGLcall("glColor3f"); + + glEnable(GL_LIGHTING); + checkGLcall("glEnable"); + + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); + checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);"); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);"); + + glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); + checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);"); + + /* switch back to the original context (unless it was zero)*/ + if (This->numberOfSwapChains != 0) { + /** TODO: restore the context and drawable **/ + glXMakeCurrent(object->display, oldDrawable, oldContext); + } + + LEAVE_GL(); + + /* TODO: move this off into a linked list implementation! (add swapchain, remove swapchain or something along those lines) */ +#if 0 + IListOperator *listOperator; + IListStore_CreateListOperator(This->swapchainStore, &listOperator); + IListOperator_Append(listOperator, (void *)object); + IListOperator_Release(listOperator); +#endif + + This->swapchains[This->numberOfSwapChains++] = (IWineD3DSwapChain *)object; + TRACE("Set swapchain to %p\n", object); + } else { /* something went wrong so clean up */ + IUnknown* bufferParent; + if (object->frontBuffer) { + IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent); + IUnknown_Release(bufferParent); /* once for the get parent */ + if(IUnknown_Release(bufferParent) > 0){ + FIXME("(%p) Something's still holding the front buffer\n",This); + } + } + if (object->backBuffer) { + IWineD3DSurface_GetParent(object->backBuffer, &bufferParent); + IUnknown_Release(bufferParent); /* once for the get parent */ + if(IUnknown_Release(bufferParent) > 0){ + FIXME("(%p) Something's still holding the back buffer\n",This); + } + } + /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */ + /* Clean up the context */ + /* check that we are the current context first (we shouldn't be though!) */ + if (object->glCtx != 0) { + if(glXGetCurrentContext() == object->glCtx){ + glXMakeCurrent(object->display, None, NULL); + } + glXDestroyContext(object->display, object->glCtx); + } + HeapFree(GetProcessHeap(), 0, object); + + } + return hr; } /** NOTE: These are ahead of the other getters and setters to save using a forward declartion **/ UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - - FIXME("(%p) : Stub\n",This); - return 1; + + /* TODO: move over to using a linked list. */ + TRACE("(%p) returning %d\n", This, This->numberOfSwapChains); + return This->numberOfSwapChains; } -HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, void** pSwapChain) { +HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - - FIXME("(%p) : Stub\n",This); + TRACE("(%p) : swapchain %d \n", This, iSwapChain); + + if(iSwapChain >= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface) || iSwapChain < 0){ + *pSwapChain = NULL; + return D3DERR_INVALIDCALL; + }else{ + /** TODO: move off to a linked list implementation **/ + *pSwapChain = This->swapchains[iSwapChain]; + } + + /* TODO: move over to using stores and linked lists. */ + + IWineD3DSwapChain_AddRef(*pSwapChain); + TRACE("(%p) returning %p\n", This, *pSwapChain); return D3D_OK; } @@ -3611,19 +4043,19 @@ HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IWineD3DSurface** ppBackBuffer) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - - *ppBackBuffer = (IWineD3DSurface *) This->backBuffer; + IWineD3DSwapChain *swapChain; + HRESULT hr; + TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer); - if (BackBuffer > This->presentParms.BackBufferCount - 1) { - FIXME("Only one backBuffer currently supported\n"); - return D3DERR_INVALIDCALL; + hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain); + if(hr == D3D_OK){ + hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer); + IWineD3DSwapChain_Release(swapChain); + }else{ + *ppBackBuffer = NULL; } - - /* Note inc ref on returned surface */ - IWineD3DSurface_AddRef(*ppBackBuffer); - - return D3D_OK; + return hr; } HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) { @@ -3632,33 +4064,19 @@ HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCA return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps); } -/** TODO: move to swapchains **/ HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - HDC hdc; - int bpp = 0; - - pMode->Width = GetSystemMetrics(SM_CXSCREEN); - pMode->Height = GetSystemMetrics(SM_CYSCREEN); - pMode->RefreshRate = 85; /*FIXME: How to identify? */ - - hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); - bpp = GetDeviceCaps(hdc, BITSPIXEL); - DeleteDC(hdc); - - switch (bpp) { - case 8: pMode->Format = WINED3DFMT_R8G8B8; break; - case 16: pMode->Format = WINED3DFMT_R5G6B5; break; - case 24: /*pMode->Format = WINED3DFMT_R8G8B8; break; */ - case 32: pMode->Format = WINED3DFMT_A8R8G8B8; break; - default: - FIXME("Unrecognized display mode format\n"); - pMode->Format = WINED3DFMT_UNKNOWN; - } + IWineD3DSwapChain *swapChain; + HRESULT hr; - FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate, - pMode->Format, debug_d3dformat(pMode->Format)); - return D3D_OK; + hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain); + if (hr == D3D_OK) { + hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode); + IWineD3DSwapChain_Release(swapChain); + }else{ + FIXME("(%p) Error getting display mode\n", This); + } + return hr; } /***** * Stateblock related functions @@ -3753,76 +4171,19 @@ HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) { HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - TRACE("(%p) Presenting the frame\n", This); - - ENTER_GL(); + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + IWineD3DSwapChain *swapChain = NULL; + int i; + int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface); - if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect); + TRACE("(%p) Presenting the frame\n", This); - glXSwapBuffers(This->display, This->drawable); - /* Don't call checkGLcall, as glGetError is not applicable here */ - - TRACE("glXSwapBuffers called, Starting new frame\n"); + for(i = 0 ; i < swapchains ; i ++){ - /* FPS support */ - if (TRACE_ON(d3d_fps)) - { - static long prev_time, frames; - - DWORD time = GetTickCount(); - frames++; - /* every 1.5 seconds */ - if (time - prev_time > 1500) { - TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time)); - prev_time = time; - frames = 0; - } - } - -#if defined(FRAME_DEBUGGING) -{ - if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) { - if (!isOn) { - isOn = TRUE; - FIXME("Enabling D3D Trace\n"); - __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1); -#if defined(SHOW_FRAME_MAKEUP) - FIXME("Singe Frame snapshots Starting\n"); - isDumpingFrames = TRUE; - glClear(GL_COLOR_BUFFER_BIT); -#endif - -#if defined(SINGLE_FRAME_DEBUGGING) - } else { -#if defined(SHOW_FRAME_MAKEUP) - FIXME("Singe Frame snapshots Finishing\n"); - isDumpingFrames = FALSE; -#endif - FIXME("Singe Frame trace complete\n"); - DeleteFileA("C:\\D3DTRACE"); - __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0); -#endif - } - } else { - if (isOn) { - isOn = FALSE; -#if defined(SHOW_FRAME_MAKEUP) - FIXME("Singe Frame snapshots Finishing\n"); - isDumpingFrames = FALSE; -#endif - FIXME("Disabling D3D Trace\n"); - __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0); - } - } -} -#endif - - LEAVE_GL(); - /* Although this is not strictly required, a simple demo showed this does occur - on (at least non-debug) d3d */ - if (This->presentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) { - IWineD3DDevice_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0); + IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain); + TRACE("presentinng chain %d, %p\n", i, swapChain); + IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0); + IWineD3DSwapChain_Release(swapChain); } return D3D_OK; @@ -4076,10 +4437,14 @@ HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, I } HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface){ - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - - TRACE("(%p) : stub\n", This); - return D3D_OK; + IWineD3DSwapChain *swapChain; + HRESULT hr; + hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain); + if(hr == D3D_OK){ + hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface); + IWineD3DSwapChain_Release(swapChain); + } + return hr; } HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) { @@ -4344,24 +4709,28 @@ HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, } void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) { - HDC hDC; - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; - - FIXME("(%p) : pRamp@%p\n", This, pRamp); - hDC = GetDC(This->win_handle); - SetDeviceGammaRamp(hDC, (LPVOID) pRamp); - ReleaseDC(This->win_handle, hDC); + IWineD3DSwapChain *swapchain; + HRESULT hrc = D3D_OK; + + TRACE("Relaying to swapchain\n"); + + if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){ + IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp); + IWineD3DSwapChain_Release(swapchain); + } return; } void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) { - HDC hDC; - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + IWineD3DSwapChain *swapchain; + HRESULT hrc = D3D_OK; - FIXME("(%p) : pRamp@%p\n", This, pRamp); - hDC = GetDC(This->win_handle); - GetDeviceGammaRamp(hDC, pRamp); - ReleaseDC(This->win_handle, hDC); + TRACE("Relaying to swapchain\n"); + + if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){ + hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp); + IWineD3DSwapChain_Release(swapchain); + } return; } diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index deb5e1925c9..e0caaf0e5de 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -4,6 +4,7 @@ * Copyright 2002-2004 Jason Edmeades * Copyright 2003-2004 Raphael Junqueira * Copyright 2004 Christian Costa + * Copyright 2005 Oliver Stieber * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -1526,15 +1527,12 @@ HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, D3DDEVT and fields being inserted in the middle, a new structure is used in place */ HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, WINED3DPRESENT_PARAMETERS* pPresentationParameters, - IWineD3DDevice** ppReturnedDeviceInterface, IUnknown *parent, D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget) { + IWineD3DDevice** ppReturnedDeviceInterface, IUnknown *parent, + D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) { - HWND whichHWND; - HDC hDc; IWineD3DDeviceImpl *object = NULL; IWineD3DImpl *This = (IWineD3DImpl *)iface; - int num; - XVisualInfo template; - HRESULT res; + IWineD3DSwapChainImpl *swapchain; /* Validate the adapter number */ if (Adapter >= IWineD3D_GetAdapterCount(iface)) { @@ -1573,242 +1571,86 @@ HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, D3DDEV object->adapterNo = Adapter; object->devType = DeviceType; - /* Setup hwnd we are using, plus which display this equates to */ - whichHWND = *(pPresentationParameters->hDeviceWindow); - if (!whichHWND) { - whichHWND = hFocusWindow; - } - object->win_handle = whichHWND; - object->win = (Window)GetPropA( whichHWND, "__wine_x11_whole_window" ); - hDc = GetDC(whichHWND); - object->display = get_display(hDc); - ReleaseDC(whichHWND, hDc); - /* FIXME: Use for dx8 code eventually too! */ /* Deliberately no indentation here, as this if will be removed when dx8 support merged in */ - if (This->dxVersion > 8) { - - /* Create a context based off the properties of the existing visual */ - /* Note the visual is chosen as the window is created and the glcontext cannot - use different properties after that point in time. FIXME: How to handle when requested format - doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one - it chooses is identical to the one already being used! */ - /* FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat */ - ENTER_GL(); - template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id"); - object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num); - if (NULL == object->visInfo) { - ERR("cannot really get XVisual\n"); - LEAVE_GL(); - return D3DERR_NOTAVAILABLE; - } - object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE); - if (NULL == object->glCtx) { - ERR("cannot create glxContext\n"); - LEAVE_GL(); - return D3DERR_NOTAVAILABLE; - } - LEAVE_GL(); - - if (object->glCtx == NULL) { - ERR("Error in context creation !\n"); - return D3DERR_INVALIDCALL; - } else { - TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n", - whichHWND, object->glCtx, object->win, object->visInfo); - } - - /* If not windowed, need to go fullscreen, and resize the HWND to the appropriate */ - /* dimensions */ - if (!*(pPresentationParameters->Windowed)) { - - DEVMODEW devmode; - HDC hdc; - int bpp = 0; - - /* Get info on the current display setup */ - hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); - bpp = GetDeviceCaps(hdc, BITSPIXEL); - DeleteDC(hdc); - - /* Change the display settings */ - memset(&devmode, 0, sizeof(DEVMODEW)); - devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /*Stupid XVidMode cannot change bpp D3DFmtGetBpp(object, pPresentationParameters->BackBufferFormat);*/ - devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth); - devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight); - MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME); - ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL); - - /* Make popup window */ - SetWindowLongA(whichHWND, GWL_STYLE, WS_POPUP); - SetWindowPos(object->win_handle, HWND_TOP, 0, 0, - *(pPresentationParameters->BackBufferWidth), - *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED); - } - - /* MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero, - then the corresponding dimension of the client area of the hDeviceWindow - (or the focus window, if hDeviceWindow is NULL) is taken. */ - if (*(pPresentationParameters->Windowed) && - ((*(pPresentationParameters->BackBufferWidth) == 0) || - (*(pPresentationParameters->BackBufferHeight) == 0))) { - - RECT Rect; - GetClientRect(whichHWND, &Rect); - - if (*(pPresentationParameters->BackBufferWidth) == 0) { - *(pPresentationParameters->BackBufferWidth) = Rect.right; - TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth)); - } - if (*(pPresentationParameters->BackBufferHeight) == 0) { - *(pPresentationParameters->BackBufferHeight) = Rect.bottom; - TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight)); - } - } - - /* Save the presentation parms now filled in correctly */ - object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth); - object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight); - object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat); - object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount); - object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType); - object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality); - object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect); - object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow); - object->presentParms.Windowed = *(pPresentationParameters->Windowed); - object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil); - object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat); - object->presentParms.Flags = *(pPresentationParameters->Flags); - object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz); - object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval); - - /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */ - IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object, - (D3DSTATEBLOCKTYPE) 0, - (IWineD3DStateBlock **)&object->stateBlock, - NULL); /* Note: No parent needed for initial internal stateblock */ - object->updateStateBlock = object->stateBlock; - - /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */ - TRACE("Creating initial device surfaces\n"); - - /* We need to 'magic' either d3d8 or d3d9 surfaces for the front and backbuuffer - but the respective CreateRenderTarget functions take a differing number of - parms. Fix this by passing in a function to call which takes identical parms - and handles the differences at the d3dx layer, and returns the IWineD3DSurface - pointer rather than the created D3D8/9 one */ - if ((res = D3DCB_CreateRenderTarget((IUnknown *) parent, - *(pPresentationParameters->BackBufferWidth), - *(pPresentationParameters->BackBufferHeight), - *(pPresentationParameters->BackBufferFormat), - *(pPresentationParameters->MultiSampleType), - *(pPresentationParameters->MultiSampleQuality), - TRUE, - (IWineD3DSurface **) &object->frontBuffer, - NULL) != D3D_OK) || - (res = D3DCB_CreateRenderTarget((IUnknown *) parent, - *(pPresentationParameters->BackBufferWidth), - *(pPresentationParameters->BackBufferHeight), - *(pPresentationParameters->BackBufferFormat), - *(pPresentationParameters->MultiSampleType), - *(pPresentationParameters->MultiSampleQuality), - TRUE, - (IWineD3DSurface **) &object->backBuffer, - NULL) != D3D_OK)) - { - ERR("D3DCB_CreateRenderTarget() failed\n"); - return res; - } - -/* TODO: - if (*(pPresentationParameters->EnableAutoDepthStencil)) { - IWineD3DDevice_CreateDepthStencilSurface((IWineD3DDevice *) object, - *(pPresentationParameters->BackBufferWidth), - *(pPresentationParameters->BackBufferHeight), - *(pPresentationParameters->AutoDepthStencilFormat, - D3DMULTISAMPLE_NONE, - (IWineD3DSurface *) &object->depthStencilBuffer); - } else { - object->depthStencilBuffer = NULL; - } - TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil @ %p\n",object->frontBuffer, object->backBuffer, object->depthStencilBuffer); -*/ + if (This->dxVersion > 8) { - /* init the default renderTarget management */ - object->drawable = object->win; - object->render_ctx = object->glCtx; - object->renderTarget = object->backBuffer; + /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */ + IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object, + (D3DSTATEBLOCKTYPE) 0, + (IWineD3DStateBlock **)&object->stateBlock, + NULL); /* Note: No parent needed for initial internal stateblock */ + object->updateStateBlock = object->stateBlock; + IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock); + /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */ + + /* Setup the implicite swapchain */ + TRACE("Creating implicite swapchain\n"); + + if (D3D_OK == D3DCB_CreateAdditionalSwapChain((IUnknown *) object->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) && swapchain != NULL) { + + object->renderTarget = swapchain->backBuffer; + IWineD3DSurface_AddRef(object->renderTarget); + /* Depth Stencil support */ + object->stencilBufferTarget = object->depthStencilBuffer; + if (NULL != object->stencilBufferTarget) { + IWineD3DSurface_AddRef(object->stencilBufferTarget); + } - IWineD3DSurface_AddRef((IWineD3DSurface *) object->renderTarget); -/* TODO: Depth Stencil support - object->stencilBufferTarget = object->depthStencilBuffer; - if (NULL != object->stencilBufferTarget) { - IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) object->stencilBufferTarget); - } -*/ - - /* Set up some starting GL setup */ - ENTER_GL(); - - if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) { - ERR("Error in setting current context (context %p drawable %ld)!\n", object->glCtx, object->win); - } - checkGLcall("glXMakeCurrent"); - - /* Clear the screen */ - glClearColor(1.0, 0.0, 0.0, 0.0); - checkGLcall("glClearColor"); - glColor3f(1.0, 1.0, 1.0); - checkGLcall("glColor3f"); - - glEnable(GL_LIGHTING); - checkGLcall("glEnable"); - - glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); - checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);"); + /* Set up some starting GL setup */ + + ENTER_GL(); + /* + * Initialize openGL extension related variables + * with Default values + */ + + This->isGLInfoValid = IWineD3DImpl_FillGLCaps(&This->gl_info, swapchain->display); + /* Setup all the devices defaults */ + IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)object->stateBlock); +#if 0 + IWineD3DImpl_CheckGraphicsMemory(); +#endif + LEAVE_GL(); + + { /* Set a default viewport */ + D3DVIEWPORT9 vp; + vp.X = 0; + vp.Y = 0; + vp.Width = *(pPresentationParameters->BackBufferWidth); + vp.Height = *(pPresentationParameters->BackBufferHeight); + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + IWineD3DDevice_SetViewport((IWineD3DDevice *)object, &vp); + } + + + /* Initialize the current view state */ + object->modelview_valid = 1; + object->proj_valid = 0; + object->view_ident = 1; + object->last_was_rhw = 0; + glGetIntegerv(GL_MAX_LIGHTS, &object->maxConcurrentLights); + TRACE("(%p,%d) All defaults now set up, leaving CreateDevice with %p\n", This, Adapter, object); + + /* Clear the screen */ + IWineD3DDevice_Clear((IWineD3DDevice *) object, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0); + } else { /* couldn't create swapchain */ + IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock); + object->updateStateBlock = NULL; + IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock); + object->stateBlock = NULL; + HeapFree(GetProcessHeap(), 0, object); + *ppReturnedDeviceInterface = NULL; + return D3DERR_INVALIDCALL; + } - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);"); + } else { /* End of FIXME: remove when dx8 merged in */ - glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); - checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);"); + FIXME("(%p) Incomplete stub for d3d8\n", This); - /* - * Initialize openGL extension related variables - * with Default values - */ - This->isGLInfoValid = IWineD3DImpl_FillGLCaps(&This->gl_info, object->display); - - /* Setup all the devices defaults */ - IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)object->stateBlock); - - LEAVE_GL(); - - { /* Set a default viewport */ - D3DVIEWPORT9 vp; - vp.X = 0; - vp.Y = 0; - vp.Width = *(pPresentationParameters->BackBufferWidth); - vp.Height = *(pPresentationParameters->BackBufferHeight); - vp.MinZ = 0.0f; - vp.MaxZ = 1.0f; - IWineD3DDevice_SetViewport((IWineD3DDevice *)object, &vp); } - /* Initialize the current view state */ - object->modelview_valid = 1; - object->proj_valid = 0; - object->view_ident = 1; - object->last_was_rhw = 0; - glGetIntegerv(GL_MAX_LIGHTS, &object->maxConcurrentLights); - TRACE("(%p,%d) All defaults now set up, leaving CreateDevice with %p\n", This, Adapter, object); - - /* Clear the screen */ - IWineD3DDevice_Clear((IWineD3DDevice *) object, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0); - - } /* End of FIXME: remove when dx8 merged in */ - return D3D_OK; } diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c new file mode 100644 index 00000000000..4dae6d29bfe --- /dev/null +++ b/dlls/wined3d/swapchain.c @@ -0,0 +1,458 @@ +/* + *IDirect3DSwapChain9 implementation + * + *Copyright 2002-2003 Jason Edmeades + *Copyright 2002-2003 Raphael Junqueira + *Copyright 2005 Oliver Stieber + * + *This library is free software; you can redistribute it and/or + *modify it under the terms of the GNU Lesser General Public + *License as published by the Free Software Foundation; either + *version 2.1 of the License, or (at your option) any later version. + * + *This library is distributed in the hope that it will be useful, + *but WITHOUT ANY WARRANTY; without even the implied warranty of + *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + *Lesser General Public License for more details. + * + *You should have received a copy of the GNU Lesser General Public + *License along with this library; if not, write to the Free Software + *Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wined3d_private.h" + + +/* TODO: move to shared header (or context manager )*/ +/* x11drv GDI escapes */ +#define X11DRV_ESCAPE 6789 +enum x11drv_escape_codes +{ + X11DRV_GET_DISPLAY, /* get X11 display for a DC */ + X11DRV_GET_DRAWABLE, /* get current drawable for a DC */ + X11DRV_GET_FONT, /* get current X font for a DC */ +}; + +/* retrieve the X display to use on a given DC */ +inline static Display *get_display( HDC hdc ) +{ + Display *display; + enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY; + + if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, + sizeof(display), (LPSTR)&display )) display = NULL; + return display; +} + +/*TODO: some of the additional parameters may be required to + set the gamma ramp (for some weird reason microsoft have left swap gammaramp in device + but it operates on a swapchain, it may be a good idea to move it to IWineD3DSwapChain for IWineD3D)*/ + + +WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(d3d_fps); + + +/* IDirect3DSwapChain IUnknown parts follow: */ +ULONG WINAPI IWineD3DSwapChainImpl_AddRef(IWineD3DSwapChain *iface) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + DWORD refCount = InterlockedIncrement(&This->ref); + TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1); + return refCount; +} + +HRESULT WINAPI IWineD3DSwapChainImpl_QueryInterface(IWineD3DSwapChain *iface, REFIID riid, LPVOID *ppobj) +{ + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + TRACE("(%p)->(%s,%p) \n",This,debugstr_guid(riid),ppobj); + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IWineD3DSwapChain)){ + IWineD3DSwapChainImpl_AddRef(iface); + if(ppobj == NULL){ + ERR("Query interface called but now data allocated\n"); + return E_NOINTERFACE; + } + *ppobj = This; + return D3D_OK; + } + return E_NOINTERFACE; +} + + +ULONG WINAPI IWineD3DSwapChainImpl_Release(IWineD3DSwapChain *iface) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + DWORD refCount; + refCount = InterlockedDecrement(&This->ref); + TRACE("(%p) : ReleaseRef to %ld\n", This, refCount); + if (refCount == 0) { + IUnknown* bufferParent; + IWineD3DSurface_GetParent(This->frontBuffer, &bufferParent); + IUnknown_Release(bufferParent); /* once for the get parent */ + if(IUnknown_Release(bufferParent) > 0){ + FIXME("(%p) Something's still holding the front buffer\n",This); + } + + IWineD3DSurface_GetParent(This->backBuffer, &bufferParent); + IUnknown_Release(bufferParent); /* once for the get parent */ + if(IUnknown_Release(bufferParent) > 0){ + FIXME("(%p) Something's still holding the back buffer\n",This); + } + /* Clean up the context */ + /* check that we are the current context first */ + if(glXGetCurrentContext() == This->glCtx){ + glXMakeCurrent(This->display, None, NULL); + } + glXDestroyContext(This->display, This->glCtx); + /* IUnknown_Release(This->parent); This should only apply to the primary swapchain, + all others are crated by the caller, so releasing the parent should cause + the child to be released, not the other way around! + */ + /* TODO: notify the device that this swapchain doesn't exist any more */ + HeapFree(GetProcessHeap(), 0, This); + } + return refCount; +} + +HRESULT WINAPI IWineD3DSwapChainImpl_GetParent(IWineD3DSwapChain *iface, IUnknown ** ppParent){ + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + *ppParent = This->parent; + IUnknown_AddRef(*ppParent); + TRACE("(%p) returning %p\n", This , *ppParent); + return D3D_OK; +} + +/*IWineD3DSwapChain parts follow: */ +HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + + ENTER_GL(); + + if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect); + /* TODO: If only source rect or dest rect are supplied then clip the window to match */ + TRACE("preseting display %p, drawable %ld\n", This->display, This->drawable); + + /* Don't call checkGLcall, as glGetError is not applicable here */ + if (hDestWindowOverride && This->win_handle != hDestWindowOverride) { + /* Set this swapchain up to point to the new destination.. */ +#ifdef USE_CONTEXT_MANAGER + /* TODO: use a context mamager */ +#endif + + /* FIXME: Never access */ + IWineD3DSwapChainImpl *swapChainImpl; + IWineD3DDevice_GetSwapChain((IWineD3DDevice *)This->wineD3DDevice, 0 , (IWineD3DSwapChain **)&swapChainImpl); + FIXME("Unable to render to a destination window %d\n", (int)hDestWindowOverride ); + if(This == swapChainImpl){ + /* FIXME: this will be fixed by moving to a context management system */ + FIXME("Cannot change the target of the implicite swapchain\n"); + }else{ + HDC hDc; + XVisualInfo template; + int num; + Display *oldDisplay = This->display; + GLXContext oldContext = This->glCtx; + IUnknown* tmp; + GLXContext currentContext; + Drawable currentDrawable; + hDc = GetDC(hDestWindowOverride); + This->win_handle = hDestWindowOverride; + This->win = (Window)GetPropA( hDestWindowOverride, "__wine_x11_whole_window" ); + + TRACE("Creating a new context for the window %p \n", hDestWindowOverride); + ENTER_GL(); + TRACE("Desctroying context %p %p\n", This->display, This->render_ctx); + + + + LEAVE_GL(); + ENTER_GL(); + + This->display = get_display(hDc); + TRACE("Got display%p for %p %p\n", This->display, hDc, hDestWindowOverride); + ReleaseDC(hDestWindowOverride, hDc); + template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id"); + This->visInfo = XGetVisualInfo(This->display, VisualIDMask, &template, &num); + if (NULL == This->visInfo) { + ERR("cannot really get XVisual\n"); + LEAVE_GL(); + return D3DERR_NOTAVAILABLE; + } + /* Now we have problems? well not really we just need to know what the implicite context is */ + /* now destroy the old context and create a new one (we should really copy the buffers over, and do the whole make current thing! */ + /* destroy the active context?*/ + TRACE("Creating new context for %p %p %p\n",This->display, This->visInfo, swapChainImpl->glCtx); + This->glCtx = glXCreateContext(This->display, This->visInfo, swapChainImpl->glCtx, GL_TRUE); + + if (NULL == This->glCtx) { + ERR("cannot create glxContext\n"); + } + This->drawable = This->win; + This->render_ctx = This->glCtx; + /* SEtup some default states TODO: apply the stateblock to the new context */ + /** save current context and drawable **/ + currentContext = glXGetCurrentContext(); + currentDrawable = glXGetCurrentDrawable(); + + if (glXMakeCurrent(This->display, This->win, This->glCtx) == False) { + ERR("Error in setting current context (display %p context %p drawable %ld)!\n", This->display, This->glCtx, This->win); + } + + checkGLcall("glXMakeCurrent"); + + /* Clear the screen */ + glClearColor(0.0, 0.0, 0.0, 0.0); + checkGLcall("glClearColor"); + glClearIndex(0); + glClearDepth(1); + glClearStencil(0); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + checkGLcall("glClear"); + + glColor3f(1.0, 1.0, 1.0); + checkGLcall("glColor3f"); + + glEnable(GL_LIGHTING); + checkGLcall("glEnable"); + + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); + checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);"); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);"); + + glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); + checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);"); + + /* If this swapchain is currently the active context then make this swapchain active */ + if(IWineD3DSurface_GetContainer((IWineD3DSurface *)This->wineD3DDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmp) == D3D_OK){ + if(tmp != (IUnknown *)This){ + glXMakeCurrent(This->display, currentDrawable, currentContext); + checkGLcall("glXMakeCurrent"); + } + IUnknown_Release(tmp); + }else{ + /* reset the context */ + glXMakeCurrent(This->display, currentDrawable, currentContext); + checkGLcall("glXMakeCurrent"); + } + /* delete the old contxt*/ + glXDestroyContext(oldDisplay, oldContext); /* Should this happen on an active context? seems a bad idea */ + LEAVE_GL(); + } + IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapChainImpl); + + } + + + /* TODO: The slow way, save the data to memory, create a new context for the destination window, transfer the data cleanup, it may be a good idea to the move this swapchain over to the using the target winows context so that it runs faster in feature. */ + + glXSwapBuffers(This->display, This->drawable); /* TODO: cycle through the swapchain buffers */ + + TRACE("glXSwapBuffers called, Starting new frame\n"); + /* FPS support */ + if (TRACE_ON(d3d_fps)) + { + static long prev_time, frames; + + DWORD time = GetTickCount(); + frames++; + /* every 1.5 seconds */ + if (time - prev_time > 1500) { + TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time)); + prev_time = time; + frames = 0; + } + } + +#if defined(FRAME_DEBUGGING) +{ + if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) { + if (!isOn) { + isOn = TRUE; + FIXME("Enabling D3D Trace\n"); + __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1); +#if defined(SHOW_FRAME_MAKEUP) + FIXME("Singe Frame snapshots Starting\n"); + isDumpingFrames = TRUE; + glClear(GL_COLOR_BUFFER_BIT); +#endif + +#if defined(SINGLE_FRAME_DEBUGGING) + } else { +#if defined(SHOW_FRAME_MAKEUP) + FIXME("Singe Frame snapshots Finishing\n"); + isDumpingFrames = FALSE; +#endif + FIXME("Singe Frame trace complete\n"); + DeleteFileA("C:\\D3DTRACE"); + __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0); +#endif + } + } else { + if (isOn) { + isOn = FALSE; +#if defined(SHOW_FRAME_MAKEUP) + FIXME("Single Frame snapshots Finishing\n"); + isDumpingFrames = FALSE; +#endif + FIXME("Disabling D3D Trace\n"); + __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0); + } + } +} +#endif + + LEAVE_GL(); + /* Although this is not strictly required, a simple demo showed this does occur + on (at least non-debug) d3d */ + if (This->presentParms.SwapEffect & D3DSWAPEFFECT_DISCARD) { + + TRACE("Clearing\n"); + + IWineD3DDevice_Clear((IWineD3DDevice*)This->wineD3DDevice, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0); + + } + TRACE("returning\n"); + return D3D_OK; +} + +HRESULT WINAPI IWineD3DSwapChainImpl_GetFrontBufferData(IWineD3DSwapChain *iface, IWineD3DSurface *pDestSurface) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pDestSurface; + GLenum format; + GLenum type; + + TRACE("(%p) : iface(%p) pDestSurface(%p) \n", This, iface, pDestSurface); + ENTER_GL(); + + /* check to see if it's the backbuffer or the frontbuffer being requested (to make sureteh data is upto date) */ + format = D3DFmt2GLFmt(This->wineD3DDevice, surface->resource.format); + type = D3DFmt2GLType(This->wineD3DDevice, surface->resource.format); + glReadBuffer(GL_FRONT); + glReadPixels(0, + 0, + surface->currentDesc.Width, + surface->currentDesc.Height, + format, + type, + surface->resource.allocatedMemory); + LEAVE_GL(); + return D3D_OK; +} + +HRESULT WINAPI IWineD3DSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *iface, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IWineD3DSurface **ppBackBuffer) { + + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + + *ppBackBuffer = (IWineD3DSurface *) This->backBuffer; + TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, iBackBuffer, Type, *ppBackBuffer); + + if (iBackBuffer > This->presentParms.BackBufferCount - 1) { + FIXME("Only one backBuffer currently supported\n"); + return D3DERR_INVALIDCALL; + } + + /* Note inc ref on returned surface */ + IWineD3DSurface_AddRef(*ppBackBuffer); + return D3D_OK; + +} + +HRESULT WINAPI IWineD3DSwapChainImpl_GetRasterStatus(IWineD3DSwapChain *iface, D3DRASTER_STATUS*pRasterStatus) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + pRasterStatus->InVBlank = TRUE; + pRasterStatus->ScanLine = 0; + FIXME("(%p) : stub\n", This); + return D3D_OK; +} + +HRESULT WINAPI IWineD3DSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, D3DDISPLAYMODE*pMode) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + HDC hdc; + int bpp = 0; + + pMode->Width = GetSystemMetrics(SM_CXSCREEN); + pMode->Height = GetSystemMetrics(SM_CYSCREEN); + pMode->RefreshRate = 85; /* FIXME: How to identify? */ + + hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); + bpp = GetDeviceCaps(hdc, BITSPIXEL); + DeleteDC(hdc); + + switch (bpp) { + case 8: pMode->Format = D3DFMT_R8G8B8; break; + case 16: pMode->Format = D3DFMT_R5G6B5; break; + case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */ /* 32bpp and 24bpp can be aliased for X */ + case 32: pMode->Format = D3DFMT_A8R8G8B8; break; + default: + FIXME("Unrecognized display mode format\n"); + pMode->Format = D3DFMT_UNKNOWN; + } + + TRACE("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate, + pMode->Format, debug_d3dformat(pMode->Format)); + return D3D_OK; +} + +HRESULT WINAPI IWineD3DSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, IWineD3DDevice**ppDevice) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + + *ppDevice = (IWineD3DDevice *) This->wineD3DDevice; + + /* Note Calling this method will increase the internal reference count + on the IDirect3DDevice9 interface. */ + IWineD3DDevice_AddRef(*ppDevice); + TRACE("(%p) : returning %p\n", This, *ppDevice); + return D3D_OK; +} + +HRESULT WINAPI IWineD3DSwapChainImpl_GetPresentParameters(IWineD3DSwapChain *iface, D3DPRESENT_PARAMETERS *pPresentationParameters) { + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + FIXME("(%p) : copy\n", This); + memcpy(pPresentationParameters, &This->presentParms, sizeof(D3DPRESENT_PARAMETERS)); + return D3D_OK; +} + +HRESULT WINAPI IWineD3DSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, DWORD Flags, CONST D3DGAMMARAMP *pRamp){ + + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + HDC hDC; + TRACE("(%p) : pRamp@%p flags(%ld) \n", This, pRamp, Flags); + hDC = GetDC(This->win_handle); + SetDeviceGammaRamp(hDC, (LPVOID)pRamp); + ReleaseDC(This->win_handle, hDC); + return D3D_OK; + +} + +HRESULT WINAPI IWineD3DSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface, D3DGAMMARAMP *pRamp){ + + IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + HDC hDC; + TRACE("(%p) : pRamp@%p\n", This, pRamp); + hDC = GetDC(This->win_handle); + GetDeviceGammaRamp(hDC, pRamp); + ReleaseDC(This->win_handle, hDC); + return D3D_OK; + +} + + +IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl = +{ + IWineD3DSwapChainImpl_QueryInterface, + IWineD3DSwapChainImpl_AddRef, + IWineD3DSwapChainImpl_Release, + IWineD3DSwapChainImpl_GetParent, + IWineD3DSwapChainImpl_GetDevice, + IWineD3DSwapChainImpl_Present, + IWineD3DSwapChainImpl_GetFrontBufferData, + IWineD3DSwapChainImpl_GetBackBuffer, + IWineD3DSwapChainImpl_GetRasterStatus, + IWineD3DSwapChainImpl_GetDisplayMode, + IWineD3DSwapChainImpl_GetPresentParameters, + IWineD3DSwapChainImpl_SetGammaRamp, + IWineD3DSwapChainImpl_GetGammaRamp +}; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index b5a8cc9e88f..d2baf7517bd 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3,7 +3,8 @@ * * Copyright 2002-2003 The wine-d3d team * Copyright 2002-2003 Raphael Junqueira - * Copyright 2004 Jason Edmeades + * Copyright 2004 Jason Edmeades + * Copyright 2005 Oliver Stieber * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -41,6 +42,9 @@ #include "wine/wined3d_interface.h" #include "wine/wined3d_gl.h" +/* Swap chains */ +#define MAX_SWAPCHAINS 256 + extern int vs_mode; #define VS_NONE 0 #define VS_HW 1 @@ -339,13 +343,6 @@ typedef struct IWineD3DDeviceImpl IWineD3D *wineD3D; /* X and GL Information */ - HWND win_handle; - Window win; - Display *display; - GLXContext glCtx; - XVisualInfo *visInfo; - GLXContext render_ctx; - Drawable drawable; GLint maxConcurrentLights; /* Optimization */ @@ -376,6 +373,10 @@ typedef struct IWineD3DDeviceImpl UINT adapterNo; D3DDEVTYPE devType; + /* TODO: Replace with a linked list */ + IWineD3DSwapChain *swapchains[MAX_SWAPCHAINS]; /* no-one wil ever need more that MAX_SWAPCHAINS swapchains */ + int numberOfSwapChains; + /* Render Target Support */ IWineD3DSurface *frontBuffer; IWineD3DSurface *backBuffer; @@ -754,6 +755,43 @@ typedef struct IWineD3DQueryImpl extern const IWineD3DQueryVtbl IWineD3DQuery_Vtbl; /***************************************************************************** + * IWineD3DSwapChainImpl implementation structure (extends IUnknown) + */ + +typedef struct IWineD3DSwapChainImpl +{ + /*IUnknown part*/ + IWineD3DSwapChainVtbl *lpVtbl; + DWORD ref; /* Note: Ref counting not required */ + + IUnknown *parent; + IWineD3DDeviceImpl *wineD3DDevice; + + /* IWineD3DSwapChain fields */ + IWineD3DSurface *backBuffer; + IWineD3DSurface *frontBuffer; + BOOL wantsDepthStencilBuffer; + D3DPRESENT_PARAMETERS presentParms; + + /* TODO: move everything upto drawable off into a context manager + and store the 'data' in the contextManagerData interface. + IUnknown *contextManagerData; + */ + + HWND win_handle; + Window win; + Display *display; + + GLXContext glCtx; + XVisualInfo *visInfo; + GLXContext render_ctx; + /* This has been left in device for now, but needs moving off into a rendertarget mamangement class and seperated out from swapchains and devices. */ + Drawable drawable; +} IWineD3DSwapChainImpl; + +extern IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl; + +/***************************************************************************** * Utility function prototypes */ diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h index 3ea951766a4..dadd8d57ed4 100644 --- a/include/wine/wined3d_interface.h +++ b/include/wine/wined3d_interface.h @@ -151,6 +151,7 @@ typedef struct IWineD3DVertexDeclaration IWineD3DVertexDeclaration; typedef struct IWineD3DVertexShader IWineD3DVertexShader; typedef struct IWineD3DPixelShader IWineD3DPixelShader; typedef struct IWineD3DQuery IWineD3DQuery; +typedef struct IWineD3DSwapChain IWineD3DSwapChain; /***************************************************************************** * Callback functions required for predefining surfaces / stencils @@ -195,11 +196,11 @@ typedef HRESULT WINAPI (*D3DCB_CREATEVOLUMEFN) (IUnknown *pDevice, DWORD Usage, IWineD3DVolume **ppVolume, HANDLE *pSharedHandle); - + typedef HRESULT WINAPI (*D3DCB_CREATEADDITIONALSWAPCHAIN) (IUnknown *pDevice, WINED3DPRESENT_PARAMETERS *pPresentationParameters, - void **pSwapChain - ); + IWineD3DSwapChain **pSwapChain + ); /***************************************************************************** * IWineD3D interface @@ -227,7 +228,8 @@ DECLARE_INTERFACE_(IWineD3D,IUnknown) STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) PURE; STDMETHOD(CheckDeviceFormatConversion)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) PURE; STDMETHOD(GetDeviceCaps)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType, WINED3DCAPS *pCaps) PURE; - STDMETHOD(CreateDevice)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType,HWND hFocusWindow, DWORD BehaviorFlags, WINED3DPRESENT_PARAMETERS * pPresentationParameters, IWineD3DDevice ** ppReturnedDeviceInterface, IUnknown *parent, D3DCB_CREATERENDERTARGETFN pFn) PURE; + STDMETHOD(CreateDevice)(THIS_ UINT Adapter, D3DDEVTYPE DeviceType,HWND hFocusWindow, DWORD BehaviorFlags, WINED3DPRESENT_PARAMETERS *pPresentationParameters, IWineD3DDevice **ppReturnedDeviceInterface, IUnknown *parent, D3DCB_CREATEADDITIONALSWAPCHAIN pFn3) PURE; + }; #undef INTERFACE @@ -278,7 +280,7 @@ DECLARE_INTERFACE_(IWineD3DDevice,IUnknown) STDMETHOD(CreateVolume)(THIS_ UINT Width, UINT Height, UINT Depth, DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DVolume** ppVolumeTexture, HANDLE* pSharedHandle, IUnknown *parent) PURE; STDMETHOD(CreateCubeTexture)(THIS_ UINT EdgeLength, UINT Levels, DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DCubeTexture** ppCubeTexture, HANDLE* pSharedHandle, IUnknown *parent, D3DCB_CREATESURFACEFN pFn) PURE; STDMETHOD(CreateQuery)(THIS_ WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown *pParent); - STDMETHOD(CreateAdditionalSwapChain)(THIS_ WINED3DPRESENT_PARAMETERS* pPresentationParameters, void** pSwapChain, IUnknown* pParent, D3DCB_CREATERENDERTARGETFN pFn, D3DCB_CREATEDEPTHSTENCILSURFACEFN pFn2); + STDMETHOD(CreateAdditionalSwapChain)(THIS_ WINED3DPRESENT_PARAMETERS *pPresentationParameters, IWineD3DSwapChain **pSwapChain, IUnknown *pParent, D3DCB_CREATERENDERTARGETFN pFn, D3DCB_CREATEDEPTHSTENCILSURFACEFN pFn2); STDMETHOD(CreateVertexDeclaration)(THIS_ CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppDecl, IUnknown* pParent) PURE; STDMETHOD(CreateVertexShader)(THIS_ CONST DWORD* pFunction, IWineD3DVertexShader** ppShader, IUnknown *pParent) PURE; STDMETHOD(CreatePixelShader)(THIS_ CONST DWORD* pFunction, IWineD3DPixelShader** ppShader, IUnknown *pParent) PURE; @@ -291,7 +293,7 @@ DECLARE_INTERFACE_(IWineD3DDevice,IUnknown) STDMETHOD(GetDisplayMode)(THIS_ UINT iSwapChain, D3DDISPLAYMODE* pMode) PURE; STDMETHOD_(UINT, GetNumberOfSwapChains)(THIS) PURE; STDMETHOD(GetRasterStatus)(THIS_ UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) PURE; - STDMETHOD(GetSwapChain)(THIS_ UINT iSwapChain, void** pSwapChain) PURE; + STDMETHOD(GetSwapChain)(THIS_ UINT iSwapChain, IWineD3DSwapChain **pSwapChain) PURE; STDMETHOD(Reset)(THIS_ WINED3DPRESENT_PARAMETERS* pPresentationParameters) PURE; STDMETHOD(SetDialogBoxMode)(THIS_ BOOL bEnableDialogs) PURE; STDMETHOD(SetCursorProperties)(THIS_ UINT XHotSpot, UINT YHotSpot, IWineD3DSurface* pCursorBitmap) PURE; @@ -1163,6 +1165,51 @@ DECLARE_INTERFACE_(IWineD3DQuery,IUnknown) #endif /***************************************************************************** + * IWineD3DSwapChain interface + * TODO: add gamma-ramp setting functions to make life easier + * (There kinda missing from Microsofts DirectX!) + */ +#define INTERFACE IWineD3DSwapChain +DECLARE_INTERFACE_(IWineD3DSwapChain,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void **ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirect3DSwapChain9 methods ***/ + STDMETHOD(GetParent)(THIS_ IUnknown **pParent) PURE; + STDMETHOD(GetDevice)(THIS_ IWineD3DDevice **ppDevice) PURE; + STDMETHOD(Present)(THIS_ CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) PURE; + STDMETHOD(GetFrontBufferData)(THIS_ IWineD3DSurface *pDestSurface) PURE; + STDMETHOD(GetBackBuffer)(THIS_ UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IWineD3DSurface **ppBackBuffer) PURE; + STDMETHOD(GetRasterStatus)(THIS_ D3DRASTER_STATUS *pRasterStatus) PURE; + STDMETHOD(GetDisplayMode)(THIS_ D3DDISPLAYMODE *pMode) PURE; + STDMETHOD(GetPresentParameters)(THIS_ D3DPRESENT_PARAMETERS *pPresentationParameters) PURE; + STDMETHOD(SetGammaRamp)(THIS_ DWORD Flags, const D3DGAMMARAMP *pRamp) PURE; + STDMETHOD(GetGammaRamp)(THIS_ D3DGAMMARAMP *pRamp) PURE; +}; +#undef INTERFACE + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IWineD3DSwapChain_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IWineD3DSwapChain_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IWineD3DSwapChain_Release(p) (p)->lpVtbl->Release(p) +/*** IWineD3DSwapChain methods ***/ + +#define IWineD3DSwapChain_GetParent(p,a) (p)->lpVtbl->GetParent(p,a) +#define IWineD3DSwapChain_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IWineD3DSwapChain_Present(p,a,b,c,d,e) (p)->lpVtbl->Present(p,a,b,c,d,e) +#define IWineD3DSwapChain_GetFrontBufferData(p,a) (p)->lpVtbl->GetFrontBufferData(p,a) +#define IWineD3DSwapChain_GetBackBuffer(p,a,b,c) (p)->lpVtbl->GetBackBuffer(p,a,b,c) +#define IWineD3DSwapChain_GetRasterStatus(p,a) (p)->lpVtbl->GetRasterStatus(p,a) +#define IWineD3DSwapChain_GetDisplayMode(p,a) (p)->lpVtbl->GetDisplayMode(p,a) +#define IWineD3DSwapChain_GetPresentParameters(p,a) (p)->lpVtbl->GetPresentParameters(p,a) +#define IWineD3DSwapChain_SetGammaRamp(p,a,b) (p)->lpVtbl->SetGammaRamp(p,a,b) +#define IWineD3DSwapChain_GetGammaRamp(p,a) (p)->lpVtbl->GetGammaRamp(p,a) +#endif + +/***************************************************************************** * IWineD3DVertexShader interface */ #define INTERFACE IWineD3DVertexShader -- 2.11.4.GIT