[PATCH 2/8] ddraw: Add a separate function for device initialization.

Henri Verbeet hverbeet at codeweavers.com
Thu Aug 19 11:57:44 CDT 2010


---
 dlls/ddraw/ddraw.c         |  109 +--------------------------------------
 dlls/ddraw/ddraw_private.h |    8 +--
 dlls/ddraw/device.c        |  124 ++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 123 insertions(+), 118 deletions(-)

diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index 20f31ee..920a365 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -4635,7 +4635,6 @@ static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid,
 {
     IDirectDrawSurfaceImpl *target = (IDirectDrawSurfaceImpl *)surface;
     IDirectDrawImpl *ddraw = ddraw_from_d3d7(iface);
-    IParentImpl *index_buffer_parent;
     IDirect3DDeviceImpl *object;
     HRESULT hr;
 
@@ -4671,122 +4670,18 @@ static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid,
         return DDERR_OUTOFMEMORY;
     }
 
-    if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
-        object->lpVtbl = &IDirect3DDevice7_FPUPreserve_Vtbl;
-    else
-        object->lpVtbl = &IDirect3DDevice7_FPUSetup_Vtbl;
-
-    object->IDirect3DDevice3_vtbl = &IDirect3DDevice3_Vtbl;
-    object->IDirect3DDevice2_vtbl = &IDirect3DDevice2_Vtbl;
-    object->IDirect3DDevice_vtbl = &IDirect3DDevice1_Vtbl;
-    object->ref = 1;
-    object->ddraw = ddraw;
-    object->target = target;
-
-    if (!ddraw_handle_table_init(&object->handle_table, 64))
-    {
-        ERR("Failed to initialize handle table.\n");
-        HeapFree(GetProcessHeap(), 0, object);
-        LeaveCriticalSection(&ddraw_cs);
-        return DDERR_OUTOFMEMORY;
-    }
-
-    object->legacyTextureBlending = FALSE;
-
-    /* Create an index buffer, it's needed for indexed drawing */
-    index_buffer_parent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*index_buffer_parent));
-    if (!index_buffer_parent)
-    {
-        ERR("Failed to allocate index buffer parent memory.\n");
-        ddraw_handle_table_destroy(&object->handle_table);
-        HeapFree(GetProcessHeap(), 0, object);
-        LeaveCriticalSection(&ddraw_cs);
-        return DDERR_OUTOFMEMORY;
-    }
-
-    ddraw_parent_init(index_buffer_parent);
-
-    /* Create an Index Buffer. WineD3D needs one for Drawing indexed primitives
-     * Create a (hopefully) long enough buffer, and copy the indices into it
-     * Ideally, a IWineD3DBuffer::SetData method could be created, which
-     * takes the pointer and avoids the memcpy. */
-    hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
-            WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, &object->indexbuffer,
-            (IUnknown *)index_buffer_parent, &ddraw_null_wined3d_parent_ops);
+    hr = d3d_device_init(object, ddraw, target);
     if (FAILED(hr))
     {
-        ERR("Failed to create an index buffer.\n");
-        HeapFree(GetProcessHeap(), 0, index_buffer_parent);
-        ddraw_handle_table_destroy(&object->handle_table);
+        WARN("Failed to initialize device, hr %#x.\n", hr);
         HeapFree(GetProcessHeap(), 0, object);
         LeaveCriticalSection(&ddraw_cs);
         return hr;
     }
-    index_buffer_parent->child = (IUnknown *)object->indexbuffer;
-
-    /* This is for convenience */
-    object->wineD3DDevice = ddraw->wineD3DDevice;
-    IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
 
     TRACE("Created device %p.\n", object);
     *device = (IDirect3DDevice7 *)object;
 
-    /* This is for apps which create a non-flip, non-d3d primary surface
-     * and an offscreen D3DDEVICE surface, then render to the offscreen surface
-     * and do a Blt from the offscreen to the primary surface.
-     *
-     * Set the offscreen D3DDDEVICE surface(=target) as the back buffer,
-     * and the primary surface(=This->d3d_target) as the front buffer.
-     *
-     * This way the app will render to the D3DDEVICE surface and WineD3D
-     * will catch the Blt was Back Buffer -> Front buffer blt and perform
-     * a flip instead. This way we don't have to deal with a mixed GL / GDI
-     * environment.
-     *
-     * This should be checked against windowed apps. The only app tested with
-     * this is moto racer 2 during the loading screen.
-     */
-    TRACE("Is rendertarget: %s, d3d_target %p.\n",
-            target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ? "true" : "false", ddraw->d3d_target);
-
-    if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
-            && ddraw->d3d_target != target)
-    {
-        TRACE("Using %p as front buffer, %p as back buffer.\n", ddraw->d3d_target, target);
-
-        hr = IWineD3DDevice_SetFrontBackBuffers(ddraw->wineD3DDevice,
-                ddraw->d3d_target->WineD3DSurface, target->WineD3DSurface);
-        if (FAILED(hr))
-        {
-            ERR("Failed to set front and back buffer, hr %#x.\n", hr);
-        }
-
-        /* Render to the back buffer */
-        IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
-        object->OffScreenTarget = TRUE;
-    }
-    else
-    {
-        object->OffScreenTarget = FALSE;
-    }
-
-    /* FIXME: This is broken. The surface AddRef() makes some sense, because
-     * we store a pointer during initialization, but then that's also where
-     * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
-    /* AddRef the render target. Also AddRef the render target from ddraw,
-     * because if it is released before the app releases the D3D device, the
-     * D3D capabilities of wined3d will be uninitialized, which has bad effects.
-     *
-     * In most cases, those surfaces are the same anyway, but this will simply
-     * add another ref which is released when the device is destroyed. */
-    IDirectDrawSurface7_AddRef(surface);
-    IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
-
-    ddraw->d3ddevice = object;
-
-    IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
-            IDirect3DDeviceImpl_UpdateDepthStencil(object));
-
     LeaveCriticalSection(&ddraw_cs);
     return D3D_OK;
 }
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index 6341f3f..5ed1676 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -393,12 +393,8 @@ struct IDirect3DDeviceImpl
     D3DMATRIXHANDLE          world, proj, view;
 };
 
-/* Vtables in various versions */
-extern const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUSetup_Vtbl DECLSPEC_HIDDEN;
-extern const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUPreserve_Vtbl DECLSPEC_HIDDEN;
-extern const IDirect3DDevice3Vtbl IDirect3DDevice3_Vtbl DECLSPEC_HIDDEN;
-extern const IDirect3DDevice2Vtbl IDirect3DDevice2_Vtbl DECLSPEC_HIDDEN;
-extern const IDirect3DDeviceVtbl  IDirect3DDevice1_Vtbl DECLSPEC_HIDDEN;
+HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw,
+        IDirectDrawSurfaceImpl *target) DECLSPEC_HIDDEN;
 
 /* The IID */
 extern const GUID IID_D3DDEVICE_WineD3D DECLSPEC_HIDDEN;
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c
index bb046b4..931b204 100644
--- a/dlls/ddraw/device.c
+++ b/dlls/ddraw/device.c
@@ -6611,7 +6611,7 @@ IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
  * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
  * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
  * by Sacrifice (game). */
-const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUSetup_Vtbl =
+static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
 {
     /*** IUnknown Methods ***/
     IDirect3DDeviceImpl_7_QueryInterface,
@@ -6666,7 +6666,7 @@ const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUSetup_Vtbl =
     IDirect3DDeviceImpl_7_GetInfo
 };
 
-const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUPreserve_Vtbl =
+static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
 {
     /*** IUnknown Methods ***/
     IDirect3DDeviceImpl_7_QueryInterface,
@@ -6721,7 +6721,7 @@ const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUPreserve_Vtbl =
     IDirect3DDeviceImpl_7_GetInfo
 };
 
-const IDirect3DDevice3Vtbl IDirect3DDevice3_Vtbl =
+static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
 {
     /*** IUnknown Methods ***/
     Thunk_IDirect3DDeviceImpl_3_QueryInterface,
@@ -6769,7 +6769,7 @@ const IDirect3DDevice3Vtbl IDirect3DDevice3_Vtbl =
     Thunk_IDirect3DDeviceImpl_3_ValidateDevice
 };
 
-const IDirect3DDevice2Vtbl IDirect3DDevice2_Vtbl =
+static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
 {
     /*** IUnknown Methods ***/
     Thunk_IDirect3DDeviceImpl_2_QueryInterface,
@@ -6808,7 +6808,7 @@ const IDirect3DDevice2Vtbl IDirect3DDevice2_Vtbl =
     Thunk_IDirect3DDeviceImpl_2_GetClipStatus
 };
 
-const IDirect3DDeviceVtbl IDirect3DDevice1_Vtbl =
+static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
 {
     /*** IUnknown Methods ***/
     Thunk_IDirect3DDeviceImpl_1_QueryInterface,
@@ -6870,3 +6870,117 @@ IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
     IDirectDrawSurface7_Release(depthStencil);
     return WINED3DZB_TRUE;
 }
+
+HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
+{
+    IParentImpl *index_buffer_parent;
+    HRESULT hr;
+
+    if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
+        device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
+    else
+        device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
+
+    device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
+    device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
+    device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
+    device->ref = 1;
+    device->ddraw = ddraw;
+    device->target = target;
+
+    if (!ddraw_handle_table_init(&device->handle_table, 64))
+    {
+        ERR("Failed to initialize handle table.\n");
+        return DDERR_OUTOFMEMORY;
+    }
+
+    device->legacyTextureBlending = FALSE;
+
+    /* Create an index buffer, it's needed for indexed drawing */
+    index_buffer_parent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*index_buffer_parent));
+    if (!index_buffer_parent)
+    {
+        ERR("Failed to allocate index buffer parent memory.\n");
+        ddraw_handle_table_destroy(&device->handle_table);
+        return DDERR_OUTOFMEMORY;
+    }
+
+    ddraw_parent_init(index_buffer_parent);
+
+    hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
+            WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, &device->indexbuffer,
+            (IUnknown *)index_buffer_parent, &ddraw_null_wined3d_parent_ops);
+    if (FAILED(hr))
+    {
+        ERR("Failed to create an index buffer, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, index_buffer_parent);
+        ddraw_handle_table_destroy(&device->handle_table);
+        return hr;
+    }
+    index_buffer_parent->child = (IUnknown *)device->indexbuffer;
+
+    /* This is for convenience. */
+    device->wineD3DDevice = ddraw->wineD3DDevice;
+    IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
+
+    /* This is for apps which create a non-flip, non-d3d primary surface
+     * and an offscreen D3DDEVICE surface, then render to the offscreen surface
+     * and do a Blt from the offscreen to the primary surface.
+     *
+     * Set the offscreen D3DDDEVICE surface(=target) as the back buffer,
+     * and the primary surface(=This->d3d_target) as the front buffer.
+     *
+     * This way the app will render to the D3DDEVICE surface and WineD3D
+     * will catch the Blt was Back Buffer -> Front buffer blt and perform
+     * a flip instead. This way we don't have to deal with a mixed GL / GDI
+     * environment.
+     *
+     * This should be checked against windowed apps. The only app tested with
+     * this is moto racer 2 during the loading screen.
+     */
+    TRACE("Is rendertarget: %s, d3d_target %p.\n",
+            target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ? "true" : "false", ddraw->d3d_target);
+
+    if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
+            && ddraw->d3d_target != target)
+    {
+        TRACE("Using %p as front buffer, %p as back buffer.\n", ddraw->d3d_target, target);
+
+        hr = IWineD3DDevice_SetFrontBackBuffers(ddraw->wineD3DDevice,
+                ddraw->d3d_target->WineD3DSurface, target->WineD3DSurface);
+        if (FAILED(hr))
+        {
+            ERR("Failed to set front and back buffer, hr %#x.\n", hr);
+            IParent_Release((IParent *)index_buffer_parent);
+            ddraw_handle_table_destroy(&device->handle_table);
+            return hr;
+        }
+
+        /* Render to the back buffer */
+        IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
+        device->OffScreenTarget = TRUE;
+    }
+    else
+    {
+        device->OffScreenTarget = FALSE;
+    }
+
+    /* FIXME: This is broken. The target AddRef() makes some sense, because
+     * we store a pointer during initialization, but then that's also where
+     * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
+    /* AddRef the render target. Also AddRef the render target from ddraw,
+     * because if it is released before the app releases the D3D device, the
+     * D3D capabilities of wined3d will be uninitialized, which has bad effects.
+     *
+     * In most cases, those surfaces are the same anyway, but this will simply
+     * add another ref which is released when the device is destroyed. */
+    IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
+    IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
+
+    ddraw->d3ddevice = device;
+
+    IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
+            IDirect3DDeviceImpl_UpdateDepthStencil(device));
+
+    return D3D_OK;
+}
-- 
1.7.1




More information about the wine-patches mailing list