Module: wine Branch: master Commit: eda929d0104a5a42f54c4be5fc840fe5f477f740 URL: http://source.winehq.org/git/wine.git/?a=commit;h=eda929d0104a5a42f54c4be5fc...
Author: Henri Verbeet hverbeet@codeweavers.com Date: Tue Feb 24 07:43:02 2009 +0100
dxgi: Create a wined3d swapchain.
---
dlls/d3d10core/device.c | 23 ++++++++++- dlls/dxgi/device.c | 33 ++++++++++++++++ dlls/dxgi/dxgi_private.h | 1 + dlls/dxgi/factory.c | 91 ++++++++++++++++++++++++++++++++++++++++---- dlls/dxgi/swapchain.c | 39 +++++++++++++++++++ include/wine/winedxgi.idl | 4 ++ 6 files changed, 179 insertions(+), 12 deletions(-)
diff --git a/dlls/d3d10core/device.c b/dlls/d3d10core/device.c index 0eeb5d9..0d79808 100644 --- a/dlls/d3d10core/device.c +++ b/dlls/d3d10core/device.c @@ -1331,11 +1331,28 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateVolume(IWineD3DDeviceParent static HRESULT STDMETHODCALLTYPE device_parent_CreateSwapChain(IWineD3DDeviceParent *iface, WINED3DPRESENT_PARAMETERS *present_parameters, IWineD3DSwapChain **swapchain) { - FIXME("iface %p, present_parameters %p, swapchain %p stub!\n", iface, present_parameters, swapchain); + IWineDXGIDevice *wine_device; + HRESULT hr;
- return E_NOTIMPL; -} + TRACE("iface %p, present_parameters %p, swapchain %p\n", iface, present_parameters, swapchain); + + hr = IWineD3DDeviceParent_QueryInterface(iface, &IID_IWineDXGIDevice, (void **)&wine_device); + if (FAILED(hr)) + { + ERR("Device should implement IWineDXGIDevice\n"); + return E_FAIL; + }
+ hr = IWineDXGIDevice_create_swapchain(wine_device, present_parameters, swapchain); + IWineDXGIDevice_Release(wine_device); + if (FAILED(hr)) + { + ERR("Failed to create DXGI swapchain, returning %#x\n", hr); + return hr; + } + + return S_OK; +}
const struct IWineD3DDeviceParentVtbl d3d10_wined3d_device_parent_vtbl = { diff --git a/dlls/dxgi/device.c b/dlls/dxgi/device.c index 5c3fdfc..bf079d5 100644 --- a/dlls/dxgi/device.c +++ b/dlls/dxgi/device.c @@ -280,6 +280,38 @@ static HRESULT STDMETHODCALLTYPE dxgi_device_create_surface(IWineDXGIDevice *ifa return S_OK; }
+static HRESULT STDMETHODCALLTYPE dxgi_device_create_swapchain(IWineDXGIDevice *iface, + WINED3DPRESENT_PARAMETERS *present_parameters, IWineD3DSwapChain **wined3d_swapchain) +{ + struct dxgi_device *This = (struct dxgi_device *)iface; + struct dxgi_swapchain *object; + HRESULT hr; + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + { + ERR("Failed to allocate DXGI swapchain object memory\n"); + return E_OUTOFMEMORY; + } + + object->vtbl = &dxgi_swapchain_vtbl; + object->refcount = 1; + + hr = IWineD3DDevice_CreateSwapChain(This->wined3d_device, present_parameters, + &object->wined3d_swapchain, (IUnknown *)object, SURFACE_OPENGL); + if (FAILED(hr)) + { + WARN("Failed to create a swapchain, returning %#x\n", hr); + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + *wined3d_swapchain = object->wined3d_swapchain; + + TRACE("Created IDXGISwapChain %p\n", object); + + return S_OK; +} + const struct IWineDXGIDeviceVtbl dxgi_device_vtbl = { /* IUnknown methods */ @@ -300,4 +332,5 @@ const struct IWineDXGIDeviceVtbl dxgi_device_vtbl = /* IWineDXGIAdapter methods */ dxgi_device_get_wined3d_device, dxgi_device_create_surface, + dxgi_device_create_swapchain, }; diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h index 90ed4dc..54446ef 100644 --- a/dlls/dxgi/dxgi_private.h +++ b/dlls/dxgi/dxgi_private.h @@ -79,6 +79,7 @@ struct dxgi_swapchain { const struct IDXGISwapChainVtbl *vtbl; LONG refcount; + IWineD3DSwapChain *wined3d_swapchain; };
/* IDXGISurface */ diff --git a/dlls/dxgi/factory.c b/dlls/dxgi/factory.c index 19bc4cf..667b2f7 100644 --- a/dlls/dxgi/factory.c +++ b/dlls/dxgi/factory.c @@ -153,25 +153,98 @@ static HRESULT STDMETHODCALLTYPE dxgi_factory_GetWindowAssociation(IWineDXGIFact return E_NOTIMPL; }
+/* TODO: The DXGI swapchain desc is a bit nicer than WINED3DPRESENT_PARAMETERS, + * change wined3d to use a structure more similar to DXGI. */ static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSwapChain(IWineDXGIFactory *iface, IUnknown *device, DXGI_SWAP_CHAIN_DESC *desc, IDXGISwapChain **swapchain) { - struct dxgi_swapchain *object; + WINED3DPRESENT_PARAMETERS present_parameters; + IWineD3DSwapChain *wined3d_swapchain; + IWineD3DDevice *wined3d_device; + IWineDXGIDevice *dxgi_device; + UINT count; + HRESULT hr;
FIXME("iface %p, device %p, desc %p, swapchain %p partial stub!\n", iface, device, desc, swapchain);
- object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); - if (!object) + hr = IUnknown_QueryInterface(device, &IID_IWineDXGIDevice, (void **)&dxgi_device); + if (FAILED(hr)) { - ERR("Failed to allocate DXGI swapchain object memory\n"); - return E_OUTOFMEMORY; + ERR("This is not the device we're looking for\n"); + return hr; }
- object->vtbl = &dxgi_swapchain_vtbl; - object->refcount = 1; - *swapchain = (IDXGISwapChain *)object; + wined3d_device = IWineDXGIDevice_get_wined3d_device(dxgi_device); + IWineDXGIDevice_Release(dxgi_device);
- TRACE("Created IDXGISwapChain %p\n", object); + count = IWineD3DDevice_GetNumberOfSwapChains(wined3d_device); + if (count) + { + FIXME("Only a single swapchain supported.\n"); + IWineD3DDevice_Release(wined3d_device); + return E_FAIL; + } + + if (!desc->OutputWindow) + { + FIXME("No output window, should use factory output window\n"); + } + + FIXME("Ignoring SwapEffect and Flags\n"); + + present_parameters.BackBufferWidth = desc->BufferDesc.Width; + present_parameters.BackBufferHeight = desc->BufferDesc.Height; + present_parameters.BackBufferFormat = wined3dformat_from_dxgi_format(desc->BufferDesc.Format); + present_parameters.BackBufferCount = desc->BufferCount; + if (desc->SampleDesc.Count > 1) + { + present_parameters.MultiSampleType = desc->SampleDesc.Count; + present_parameters.MultiSampleQuality = desc->SampleDesc.Quality; + } + else + { + present_parameters.MultiSampleType = WINED3DMULTISAMPLE_NONE; + present_parameters.MultiSampleQuality = 0; + } + present_parameters.SwapEffect = WINED3DSWAPEFFECT_DISCARD; + present_parameters.hDeviceWindow = desc->OutputWindow; + present_parameters.Windowed = desc->Windowed; + present_parameters.EnableAutoDepthStencil = FALSE; + present_parameters.AutoDepthStencilFormat = 0; + present_parameters.Flags = 0; /* WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL? */ + present_parameters.FullScreen_RefreshRateInHz = + desc->BufferDesc.RefreshRate.Numerator / desc->BufferDesc.RefreshRate.Denominator; + present_parameters.PresentationInterval = WINED3DPRESENT_INTERVAL_DEFAULT; + + hr = IWineD3DDevice_Init3D(wined3d_device, &present_parameters); + if (FAILED(hr)) + { + WARN("Failed to initialize 3D, returning %#x\n", hr); + IWineD3DDevice_Release(wined3d_device); + return hr; + } + + hr = IWineD3DDevice_GetSwapChain(wined3d_device, 0, &wined3d_swapchain); + IWineD3DDevice_Release(wined3d_device); + if (FAILED(hr)) + { + WARN("Failed to get swapchain, returning %#x\n", hr); + return hr; + } + + hr = IWineD3DSwapChain_GetParent(wined3d_swapchain, (IUnknown **)swapchain); + IUnknown_Release(wined3d_swapchain); + if (FAILED(hr)) + { + WARN("Failed to get swapchain, returning %#x\n", hr); + return hr; + } + + /* FIXME? The swapchain is created with refcount 1 by the wined3d device, + * but the wined3d device can't hold a real reference. */ + IUnknown_Release(*swapchain); + + TRACE("Created IDXGISwapChain %p\n", *swapchain);
return S_OK; } diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 3287c4c..3e9e444 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -56,6 +56,25 @@ static ULONG STDMETHODCALLTYPE dxgi_swapchain_AddRef(IDXGISwapChain *iface) return refcount; }
+static ULONG STDMETHODCALLTYPE destroy_surface(IWineD3DSurface *surface) +{ + IDXGISurface *dxgi_surface; + + TRACE("surface %p\n", surface); + + IWineD3DSurface_GetParent(surface, (IUnknown **)&dxgi_surface); + IDXGISurface_Release(dxgi_surface); + + return IDXGISurface_Release(dxgi_surface); +} + +static ULONG STDMETHODCALLTYPE destroy_swapchain(IWineD3DSwapChain *swapchain) +{ + TRACE("swapchain %p\n", swapchain); + + return IWineD3DSwapChain_Release(swapchain); +} + static ULONG STDMETHODCALLTYPE dxgi_swapchain_Release(IDXGISwapChain *iface) { struct dxgi_swapchain *This = (struct dxgi_swapchain *)iface; @@ -65,6 +84,26 @@ static ULONG STDMETHODCALLTYPE dxgi_swapchain_Release(IDXGISwapChain *iface)
if (!refcount) { + IWineD3DDevice *wined3d_device; + HRESULT hr; + + FIXME("Only a single swapchain is supported\n"); + + hr = IWineD3DSwapChain_GetDevice(This->wined3d_swapchain, &wined3d_device); + if (FAILED(hr)) + { + ERR("Failed to get the wined3d device, hr %#x\n", hr); + } + else + { + hr = IWineD3DDevice_Uninit3D(wined3d_device, destroy_surface, destroy_swapchain); + IWineD3DDevice_Release(wined3d_device); + if (FAILED(hr)) + { + ERR("Uninit3D failed, hr %#x\n", hr); + } + } + HeapFree(GetProcessHeap(), 0, This); }
diff --git a/include/wine/winedxgi.idl b/include/wine/winedxgi.idl index 3fc7883..e54ce73 100644 --- a/include/wine/winedxgi.idl +++ b/include/wine/winedxgi.idl @@ -53,4 +53,8 @@ interface IWineDXGIDevice : IDXGIDevice [in] IUnknown *outer, [out] void **surface ); + HRESULT create_swapchain( + [in] struct _WINED3DPRESENT_PARAMETERS *present_parameters, + [out] struct IWineD3DSwapChain **wined3d_swapchain + ); }