[PATCH 3/5] d3d9: Update swapchain surfaces after presenting (v2).

Stefan Dösinger stefan at codeweavers.com
Thu Oct 8 13:09:44 CDT 2015


Version 2: num_back_buffers -> back_buffer_count.

Signed-off-by: Stefan Dösinger <stefan at codeweavers.com>
---
 dlls/d3d9/d3d9_private.h |  6 ++++
 dlls/d3d9/device.c       | 14 ++++++---
 dlls/d3d9/swapchain.c    | 76 +++++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 84 insertions(+), 12 deletions(-)

diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
index d44add8..2dcf8ff 100644
--- a/dlls/d3d9/d3d9_private.h
+++ b/dlls/d3d9/d3d9_private.h
@@ -208,10 +208,16 @@ struct d3d9_swapchain
     LONG refcount;
     struct wined3d_swapchain *wined3d_swapchain;
     IDirect3DDevice9Ex *parent_device;
+
+    UINT back_buffer_count;
+    struct d3d9_surface **back_buffers;
 };
 
 HRESULT d3d9_swapchain_create(struct d3d9_device *device, struct wined3d_swapchain_desc *desc,
         struct d3d9_swapchain **swapchain) DECLSPEC_HIDDEN;
+HRESULT d3d9_swapchain_get_back_buffers(struct d3d9_swapchain *swapchain) DECLSPEC_HIDDEN;
+HRESULT d3d9_swapchain_present_internal(struct d3d9_swapchain *swapchain, const RECT *src_rect,
+        const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region, DWORD flags) DECLSPEC_HIDDEN;
 
 struct d3d9_surface
 {
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index de27dbf..5f70baf 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -649,6 +649,7 @@ static HRESULT d3d9_device_get_swapchains(struct d3d9_device *device)
 {
     UINT i, new_swapchain_count = wined3d_device_get_swapchain_count(device->wined3d_device);
     struct wined3d_swapchain *wined3d_swapchain;
+    HRESULT hr;
 
     if (!(device->implicit_swapchains = HeapAlloc(GetProcessHeap(), 0,
             new_swapchain_count * sizeof(*device->implicit_swapchains))))
@@ -658,6 +659,11 @@ static HRESULT d3d9_device_get_swapchains(struct d3d9_device *device)
     {
         wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, i);
         device->implicit_swapchains[i] = wined3d_swapchain_get_parent(wined3d_swapchain);
+
+        HeapFree(GetProcessHeap(), 0, device->implicit_swapchains[i]->back_buffers);
+        if (FAILED(hr = d3d9_swapchain_get_back_buffers(device->implicit_swapchains[i])))
+            return hr;
+
     }
     device->implicit_swapchain_count = new_swapchain_count;
 
@@ -762,8 +768,8 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex *
     wined3d_mutex_lock();
     for (i = 0; i < device->implicit_swapchain_count; ++i)
     {
-        hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain, src_rect,
-                dst_rect, dst_window_override, dirty_region, 0);
+        hr = d3d9_swapchain_present_internal(device->implicit_swapchains[i], src_rect, dst_rect,
+                dst_window_override, dirty_region, 0);
         if (FAILED(hr))
         {
             wined3d_mutex_unlock();
@@ -3225,8 +3231,8 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_PresentEx(IDirect3DDevice9Ex
     wined3d_mutex_lock();
     for (i = 0; i < device->implicit_swapchain_count; ++i)
     {
-        if (FAILED(hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain, src_rect,
-                dst_rect, dst_window_override, dirty_region, flags)))
+        if (FAILED(hr = d3d9_swapchain_present_internal(device->implicit_swapchains[i], src_rect, dst_rect,
+                dst_window_override, dirty_region, flags)))
         {
             wined3d_mutex_unlock();
             return hr;
diff --git a/dlls/d3d9/swapchain.c b/dlls/d3d9/swapchain.c
index 1355a95..15cfa95 100644
--- a/dlls/d3d9/swapchain.c
+++ b/dlls/d3d9/swapchain.c
@@ -110,6 +110,35 @@ static ULONG WINAPI d3d9_swapchain_Release(IDirect3DSwapChain9Ex *iface)
     return refcount;
 }
 
+/* Don't call the public function from d3d9_device_Present to prevent hooks from being called twice.
+ * In d3d8 fraps only hooks swapchain::present, suggesting that the native device method calls the
+ * swapchain method. In d3d9 Fraps hooks both. */
+HRESULT d3d9_swapchain_present_internal(struct d3d9_swapchain *swapchain, const RECT *src_rect,
+        const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region, DWORD flags)
+{
+    HRESULT hr;
+    UINT i;
+    struct wined3d_texture *texture;
+    struct wined3d_resource *resource;
+    struct wined3d_surface *surface;
+
+    if (FAILED(hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, src_rect,
+            dst_rect, dst_window_override, dirty_region, flags)))
+        return hr;
+
+    for (i = 0; i < swapchain->back_buffer_count; ++i)
+    {
+        texture = wined3d_swapchain_get_back_buffer(swapchain->wined3d_swapchain, i);
+        resource = wined3d_texture_get_sub_resource(texture, 0);
+        surface = wined3d_surface_from_resource(resource);
+
+        swapchain->back_buffers[i]->wined3d_surface = surface;
+        wined3d_resource_set_parent(resource, swapchain->back_buffers[i]);
+    }
+
+    return hr;
+}
+
 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_swapchain_Present(IDirect3DSwapChain9Ex *iface,
         const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
         const RGNDATA *dirty_region, DWORD flags)
@@ -122,8 +151,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_swapchain_Present(IDirect3DSwapChai
         return device->d3d_parent->extended ? S_PRESENT_OCCLUDED : D3DERR_DEVICELOST;
 
     wined3d_mutex_lock();
-    hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, src_rect,
-            dst_rect, dst_window_override, dirty_region, flags);
+    hr = d3d9_swapchain_present_internal(swapchain, src_rect, dst_rect, dst_window_override, dirty_region, flags);
     wined3d_mutex_unlock();
 
     return hr;
@@ -323,7 +351,9 @@ static const struct IDirect3DSwapChain9ExVtbl d3d9_swapchain_vtbl =
 
 static void STDMETHODCALLTYPE d3d9_swapchain_wined3d_object_released(void *parent)
 {
-    HeapFree(GetProcessHeap(), 0, parent);
+    struct d3d9_swapchain *swapchain = parent;
+    HeapFree(GetProcessHeap(), 0, swapchain->back_buffers);
+    HeapFree(GetProcessHeap(), 0, swapchain);
 }
 
 static const struct wined3d_parent_ops d3d9_swapchain_wined3d_parent_ops =
@@ -331,6 +361,30 @@ static const struct wined3d_parent_ops d3d9_swapchain_wined3d_parent_ops =
     d3d9_swapchain_wined3d_object_released,
 };
 
+HRESULT d3d9_swapchain_get_back_buffers(struct d3d9_swapchain *swapchain)
+{
+    struct wined3d_swapchain_desc desc;
+    struct wined3d_texture *texture;
+    struct wined3d_resource *resource;
+    UINT i;
+
+    wined3d_swapchain_get_desc(swapchain->wined3d_swapchain, &desc);
+    swapchain->back_buffers = HeapAlloc(GetProcessHeap(), 0,
+            desc.backbuffer_count * sizeof(*swapchain->back_buffers));
+    if (!swapchain->back_buffers)
+        return E_OUTOFMEMORY;
+
+    for (i = 0; i < desc.backbuffer_count; ++i)
+    {
+        texture = wined3d_swapchain_get_back_buffer(swapchain->wined3d_swapchain, i);
+        resource = wined3d_texture_get_sub_resource(texture, 0);
+        swapchain->back_buffers[i] = wined3d_resource_get_parent(resource);
+    }
+    swapchain->back_buffer_count = desc.backbuffer_count;
+
+    return D3D_OK;
+}
+
 static HRESULT swapchain_init(struct d3d9_swapchain *swapchain, struct d3d9_device *device,
         struct wined3d_swapchain_desc *desc)
 {
@@ -340,16 +394,22 @@ static HRESULT swapchain_init(struct d3d9_swapchain *swapchain, struct d3d9_devi
     swapchain->IDirect3DSwapChain9Ex_iface.lpVtbl = &d3d9_swapchain_vtbl;
 
     wined3d_mutex_lock();
-    hr = wined3d_swapchain_create(device->wined3d_device, desc, swapchain,
-            &d3d9_swapchain_wined3d_parent_ops, &swapchain->wined3d_swapchain);
-    wined3d_mutex_unlock();
-
-    if (FAILED(hr))
+    if (FAILED(hr = wined3d_swapchain_create(device->wined3d_device, desc, swapchain,
+            &d3d9_swapchain_wined3d_parent_ops, &swapchain->wined3d_swapchain)))
     {
+        wined3d_mutex_unlock();
         WARN("Failed to create wined3d swapchain, hr %#x.\n", hr);
         return hr;
     }
 
+    if (FAILED(hr = d3d9_swapchain_get_back_buffers(swapchain)))
+    {
+        wined3d_swapchain_decref(swapchain->wined3d_swapchain);
+        wined3d_mutex_unlock();
+        return hr;
+    }
+    wined3d_mutex_unlock();
+
     swapchain->parent_device = &device->IDirect3DDevice9Ex_iface;
     IDirect3DDevice9Ex_AddRef(swapchain->parent_device);
 
-- 
2.4.9




More information about the wine-patches mailing list