From: Stefan Dösinger Subject: [PATCH 1/5] d3d8: Call IDirect3DSwapChain8::Present in IDirect3DDevice8::Present. Message-Id: <1435059566-11498-1-git-send-email-stefan@codeweavers.com> Date: Tue, 23 Jun 2015 13:39:22 +0200 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