[PATCH 1/5] d3d8: Call IDirect3DSwapChain8::Present in IDirect3DDevice8::Present.

Stefan Dösinger stefan at codeweavers.com
Tue Jun 23 06:39:22 CDT 2015


Freeing device->swapchains in the error path is technically redundant
because there's no "goto err" after a successful allocation of this
field. I put it there to avoid potential memory leaks with future
changes.
---
 dlls/d3d8/d3d8_private.h |  4 ++++
 dlls/d3d8/device.c       | 44 ++++++++++++++++++++++++++++++++++++--------
 2 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h
index 6283c8d..497da3f 100644
--- a/dlls/d3d8/d3d8_private.h
+++ b/dlls/d3d8/d3d8_private.h
@@ -176,6 +176,10 @@ struct d3d8_device
     LONG device_state;
     /* Avoids recursion with nested ReleaseRef to 0 */
     BOOL                    inDestruction;
+
+    /* Swapchain cache for Present */
+    UINT                    num_swapchains;
+    IDirect3DSwapChain8     **swapchains;
 };
 
 HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wined3d *wined3d, UINT adapter,
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index 26cc9ac..98b4f03 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -351,6 +351,7 @@ static ULONG WINAPI d3d8_device_Release(IDirect3DDevice8 *iface)
 
         device->inDestruction = TRUE;
 
+        HeapFree(GetProcessHeap(), 0, device->swapchains);
         for (i = 0; i < device->numConvertedDecls; ++i)
         {
             d3d8_vertex_declaration_destroy(device->decls[i].declaration);
@@ -688,19 +689,25 @@ static HRESULT WINAPI d3d8_device_Present(IDirect3DDevice8 *iface, const RECT *s
 {
     struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
     HRESULT hr;
+    UINT i;
 
     TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p.\n",
             iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect), dst_window_override, dirty_region);
 
-    if (device->device_state != D3D8_DEVICE_STATE_OK)
-        return D3DERR_DEVICELOST;
-
-    wined3d_mutex_lock();
-    hr = wined3d_device_present(device->wined3d_device, src_rect, dst_rect,
-            dst_window_override, dirty_region, 0);
-    wined3d_mutex_unlock();
+    /* Fraps does not hook IDirect3DDevice8::Present regardless of the hotpatch
+     * attribute. It only hooks IDirect3DSwapChain8::Present. Yet it properly
+     * shows a framerate on Windows in applications that only call the device
+     * method, like e.g. the dx8 sdk samples. The conclusion is that native
+     * calls the swapchain's public method from the device. */
+    for (i = 0; i < device->num_swapchains; i++)
+    {
+        hr = IDirect3DSwapChain8_Present(device->swapchains[i], src_rect,
+                dst_rect, dst_window_override, dirty_region);
+        if (FAILED(hr))
+            return hr;
+    }
 
-    return hr;
+    return D3D_OK;
 }
 
 static HRESULT WINAPI d3d8_device_GetBackBuffer(IDirect3DDevice8 *iface,
@@ -3091,6 +3098,7 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wine
 {
     struct wined3d_swapchain_desc swapchain_desc;
     HRESULT hr;
+    UINT i;
 
     device->IDirect3DDevice8_iface.lpVtbl = &d3d8_device_vtbl;
     device->device_parent.ops = &d3d8_wined3d_device_parent_ops;
@@ -3169,6 +3177,24 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wine
         goto err;
     }
 
+    device->num_swapchains = wined3d_device_get_swapchain_count(device->wined3d_device);
+    device->swapchains = HeapAlloc(GetProcessHeap(), 0, sizeof(*device->swapchains) * device->num_swapchains);
+    if (!device->swapchains)
+    {
+        hr = E_OUTOFMEMORY;
+        goto err;
+    }
+
+    for (i = 0; i < device->num_swapchains; i++)
+    {
+        struct wined3d_swapchain *wined3d_swapchain;
+        struct d3d8_swapchain *swapchain_impl;
+
+        wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, i);
+        swapchain_impl = wined3d_swapchain_get_parent(wined3d_swapchain);
+        device->swapchains[i] = &swapchain_impl->IDirect3DSwapChain8_iface;
+    }
+
     device->d3d_parent = &parent->IDirect3D8_iface;
     IDirect3D8_AddRef(device->d3d_parent);
 
@@ -3176,6 +3202,8 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wine
 
 err:
     wined3d_mutex_lock();
+    HeapFree(GetProcessHeap(), 0, device->swapchains);
+    HeapFree(GetProcessHeap(), 0, device->decls);
     wined3d_device_uninit_3d(device->wined3d_device);
     wined3d_device_release_focus_window(device->wined3d_device);
     wined3d_device_decref(device->wined3d_device);
-- 
2.3.6




More information about the wine-patches mailing list