diff --git a/dlls/d3d10core/device.c b/dlls/d3d10core/device.c index 0eeb5d93d23..0d798085e60 100644 --- a/dlls/d3d10core/device.c +++ b/dlls/d3d10core/device.c @@ -1331,12 +1331,29 @@ 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 = { /* IUnknown methods */ diff --git a/dlls/dxgi/device.c b/dlls/dxgi/device.c index 5c3fdfcf228..bf079d5daaf 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 90ed4dc75ca..54446efcd6b 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 19bc4cf7fc3..667b2f773ba 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 3287c4c27bd..3e9e4440d39 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 3fc7883168f..e54ce73d042 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 + ); }