[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