From: Stefan Dösinger Subject: [PATCH 3/8] d3d9: Update swapchain surfaces after presenting. Message-Id: <1442251072-16952-3-git-send-email-stefan@codeweavers.com> Date: Mon, 14 Sep 2015 19:17:47 +0200 --- 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 4a6dc0c..62a2803 100644 --- a/dlls/d3d9/d3d9_private.h +++ b/dlls/d3d9/d3d9_private.h @@ -207,10 +207,16 @@ struct d3d9_swapchain LONG refcount; struct wined3d_swapchain *wined3d_swapchain; IDirect3DDevice9Ex *parent_device; + + UINT num_back_buffers; + 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 2a60b14..645d62c 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->num_implicit_swapchains = new_swapchain_count; @@ -762,8 +768,8 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex * wined3d_mutex_lock(); for (i = 0; i < device->num_implicit_swapchains; ++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->num_implicit_swapchains; ++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..53375e4 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->num_back_buffers; ++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->num_back_buffers = 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.6