[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