=?UTF-8?Q?J=C3=B3zef=20Kucia=20?=: d3d9: Do not create render target view while surface refcount is equal to 0.

Alexandre Julliard julliard at winehq.org
Fri Jan 6 13:54:10 CST 2017


Module: wine
Branch: master
Commit: e8360b8eaa802c8854cf357479f33b7e3d4b4dfe
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e8360b8eaa802c8854cf357479f33b7e3d4b4dfe

Author: Józef Kucia <jkucia at codeweavers.com>
Date:   Fri Jan  6 10:33:54 2017 +0100

d3d9: Do not create render target view while surface refcount is equal to 0.

This fixes a regression introduced by commit
b005ad6f905dc0051b17ea45b3690e0662e48481.

A render target view has to be created when a surface is referenced.
Otherwise the render target view reference count would be inconsistent
with the surface reference count.

Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/d3d9/d3d9_private.h |  4 +++-
 dlls/d3d9/device.c       | 18 ++++++++++++------
 dlls/d3d9/surface.c      | 15 ++++++++++++++-
 dlls/d3d9/tests/visual.c |  9 ++++-----
 4 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
index 20c4c5c..fef0133 100644
--- a/dlls/d3d9/d3d9_private.h
+++ b/dlls/d3d9/d3d9_private.h
@@ -230,8 +230,10 @@ struct d3d9_surface
     struct d3d9_texture *texture;
 };
 
+struct wined3d_rendertarget_view *d3d9_surface_acquire_rendertarget_view(struct d3d9_surface *surface) DECLSPEC_HIDDEN;
 struct d3d9_device *d3d9_surface_get_device(const struct d3d9_surface *surface) DECLSPEC_HIDDEN;
-struct wined3d_rendertarget_view *d3d9_surface_get_rendertarget_view(struct d3d9_surface *surface) DECLSPEC_HIDDEN;
+void d3d9_surface_release_rendertarget_view(struct d3d9_surface *surface,
+        struct wined3d_rendertarget_view *rtv) DECLSPEC_HIDDEN;
 void surface_init(struct d3d9_surface *surface, struct wined3d_texture *wined3d_texture,
         unsigned int sub_resource_idx, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
 struct d3d9_surface *unsafe_impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface) DECLSPEC_HIDDEN;
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index d47c705..e6ddaf4 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -1421,6 +1421,7 @@ static HRESULT WINAPI d3d9_device_ColorFill(IDirect3DDevice9Ex *iface,
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
     struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface);
     struct wined3d_sub_resource_desc desc;
+    struct wined3d_rendertarget_view *rtv;
     HRESULT hr;
 
     TRACE("iface %p, surface %p, rect %p, color 0x%08x.\n", iface, surface, rect, color);
@@ -1453,9 +1454,10 @@ static HRESULT WINAPI d3d9_device_ColorFill(IDirect3DDevice9Ex *iface,
         return D3DERR_INVALIDCALL;
     }
 
+    rtv = d3d9_surface_acquire_rendertarget_view(surface_impl);
     hr = wined3d_device_clear_rendertarget_view(device->wined3d_device,
-            d3d9_surface_get_rendertarget_view(surface_impl), rect,
-            WINED3DCLEAR_TARGET, &c, 0.0f, 0);
+            rtv, rect, WINED3DCLEAR_TARGET, &c, 0.0f, 0);
+    d3d9_surface_release_rendertarget_view(surface_impl, rtv);
 
     wined3d_mutex_unlock();
 
@@ -1511,6 +1513,7 @@ static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWO
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
     struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface);
+    struct wined3d_rendertarget_view *rtv;
     HRESULT hr;
 
     TRACE("iface %p, idx %u, surface %p.\n", iface, idx, surface);
@@ -1534,8 +1537,9 @@ static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWO
     }
 
     wined3d_mutex_lock();
-    hr = wined3d_device_set_rendertarget_view(device->wined3d_device, idx,
-            surface_impl ? d3d9_surface_get_rendertarget_view(surface_impl) : NULL, TRUE);
+    rtv = surface_impl ? d3d9_surface_acquire_rendertarget_view(surface_impl) : NULL;
+    hr = wined3d_device_set_rendertarget_view(device->wined3d_device, idx, rtv, TRUE);
+    d3d9_surface_release_rendertarget_view(surface_impl, rtv);
     wined3d_mutex_unlock();
 
     return hr;
@@ -1582,12 +1586,14 @@ static HRESULT WINAPI d3d9_device_SetDepthStencilSurface(IDirect3DDevice9Ex *ifa
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
     struct d3d9_surface *ds_impl = unsafe_impl_from_IDirect3DSurface9(depth_stencil);
+    struct wined3d_rendertarget_view *rtv;
 
     TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
 
     wined3d_mutex_lock();
-    wined3d_device_set_depth_stencil_view(device->wined3d_device,
-            ds_impl ? d3d9_surface_get_rendertarget_view(ds_impl) : NULL);
+    rtv = ds_impl ? d3d9_surface_acquire_rendertarget_view(ds_impl) : NULL;
+    wined3d_device_set_depth_stencil_view(device->wined3d_device, rtv);
+    d3d9_surface_release_rendertarget_view(ds_impl, rtv);
     wined3d_mutex_unlock();
 
     return D3D_OK;
diff --git a/dlls/d3d9/surface.c b/dlls/d3d9/surface.c
index 12e0f39..2f8d447 100644
--- a/dlls/d3d9/surface.c
+++ b/dlls/d3d9/surface.c
@@ -396,10 +396,15 @@ struct d3d9_device *d3d9_surface_get_device(const struct d3d9_surface *surface)
     return impl_from_IDirect3DDevice9Ex(device);
 }
 
-struct wined3d_rendertarget_view *d3d9_surface_get_rendertarget_view(struct d3d9_surface *surface)
+struct wined3d_rendertarget_view *d3d9_surface_acquire_rendertarget_view(struct d3d9_surface *surface)
 {
     HRESULT hr;
 
+    /* The surface reference count can be equal to 0 when this function is
+     * called. In order to properly manage the render target view reference
+     * count, we temporarily increment the surface reference count. */
+    d3d9_surface_AddRef(&surface->IDirect3DSurface9_iface);
+
     if (surface->wined3d_rtv)
         return surface->wined3d_rtv;
 
@@ -407,6 +412,7 @@ struct wined3d_rendertarget_view *d3d9_surface_get_rendertarget_view(struct d3d9
             surface->sub_resource_idx, surface, &d3d9_view_wined3d_parent_ops, &surface->wined3d_rtv)))
     {
         ERR("Failed to create rendertarget view, hr %#x.\n", hr);
+        d3d9_surface_Release(&surface->IDirect3DSurface9_iface);
         return NULL;
     }
 
@@ -416,6 +422,13 @@ struct wined3d_rendertarget_view *d3d9_surface_get_rendertarget_view(struct d3d9
     return surface->wined3d_rtv;
 }
 
+void d3d9_surface_release_rendertarget_view(struct d3d9_surface *surface,
+        struct wined3d_rendertarget_view *rtv)
+{
+    if (rtv)
+        d3d9_surface_Release(&surface->IDirect3DSurface9_iface);
+}
+
 struct d3d9_surface *unsafe_impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface)
 {
     if (!iface)
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index d23be17..43c0cbc 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -22223,7 +22223,6 @@ static void test_max_index16(void)
     DestroyWindow(window);
 }
 
-/* This test exercises a regression in Wine d3d9 implementation. */
 static void test_backbuffer_resize(void)
 {
     D3DPRESENT_PARAMETERS present_parameters = {0};
@@ -22257,8 +22256,8 @@ static void test_backbuffer_resize(void)
         goto done;
     }
 
-    /* In order to exercise the regression the backbuffer surface has to be
-     * unreferenced when SetRenderTarget() is called. */
+    /* Wine d3d9 implementation had a bug which was triggered by a
+     * SetRenderTarget() call with an unreferenced surface. */
     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
     ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
     refcount = IDirect3DSurface9_Release(backbuffer);
@@ -22304,7 +22303,7 @@ static void test_backbuffer_resize(void)
     color = getPixelColor(device, 1, 1);
     ok(color == 0x00ffff00, "Got unexpected color 0x%08x.\n", color);
     color = getPixelColor(device, 700, 500);
-    todo_wine ok(color == 0x00ffff00, "Got unexpected color 0x%08x.\n", color);
+    ok(color == 0x00ffff00, "Got unexpected color 0x%08x.\n", color);
 
     hr = IDirect3DDevice9_BeginScene(device);
     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
@@ -22315,7 +22314,7 @@ static void test_backbuffer_resize(void)
     color = getPixelColor(device, 1, 1);
     ok(color == 0x0000ff00, "Got unexpected color 0x%08x.\n", color);
     color = getPixelColor(device, 700, 500);
-    todo_wine ok(color == 0x0000ff00, "Got unexpected color 0x%08x.\n", color);
+    ok(color == 0x0000ff00, "Got unexpected color 0x%08x.\n", color);
 
     refcount = IDirect3DDevice9_Release(device);
     ok(!refcount, "Device has %u references left.\n", refcount);




More information about the wine-cvs mailing list