Henri Verbeet : dxgi: Create a wined3d swapchain.

Alexandre Julliard julliard at winehq.org
Tue Feb 24 10:21:32 CST 2009


Module: wine
Branch: master
Commit: eda929d0104a5a42f54c4be5fc840fe5f477f740
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=eda929d0104a5a42f54c4be5fc840fe5f477f740

Author: Henri Verbeet <hverbeet at 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
+    );
 }




More information about the wine-cvs mailing list