Commit e8360b8e authored by Józef Kucia's avatar Józef Kucia Committed by Alexandre Julliard

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

This fixes a regression introduced by commit b005ad6f. 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: 's avatarJózef Kucia <jkucia@codeweavers.com> Signed-off-by: 's avatarHenri Verbeet <hverbeet@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent da5a0b76
...@@ -230,8 +230,10 @@ struct d3d9_surface ...@@ -230,8 +230,10 @@ struct d3d9_surface
struct d3d9_texture *texture; 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 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, 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; 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; struct d3d9_surface *unsafe_impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface) DECLSPEC_HIDDEN;
......
...@@ -1421,6 +1421,7 @@ static HRESULT WINAPI d3d9_device_ColorFill(IDirect3DDevice9Ex *iface, ...@@ -1421,6 +1421,7 @@ static HRESULT WINAPI d3d9_device_ColorFill(IDirect3DDevice9Ex *iface,
struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface); struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface);
struct wined3d_sub_resource_desc desc; struct wined3d_sub_resource_desc desc;
struct wined3d_rendertarget_view *rtv;
HRESULT hr; HRESULT hr;
TRACE("iface %p, surface %p, rect %p, color 0x%08x.\n", iface, surface, rect, color); 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, ...@@ -1453,9 +1454,10 @@ static HRESULT WINAPI d3d9_device_ColorFill(IDirect3DDevice9Ex *iface,
return D3DERR_INVALIDCALL; return D3DERR_INVALIDCALL;
} }
rtv = d3d9_surface_acquire_rendertarget_view(surface_impl);
hr = wined3d_device_clear_rendertarget_view(device->wined3d_device, hr = wined3d_device_clear_rendertarget_view(device->wined3d_device,
d3d9_surface_get_rendertarget_view(surface_impl), rect, rtv, rect, WINED3DCLEAR_TARGET, &c, 0.0f, 0);
WINED3DCLEAR_TARGET, &c, 0.0f, 0); d3d9_surface_release_rendertarget_view(surface_impl, rtv);
wined3d_mutex_unlock(); wined3d_mutex_unlock();
...@@ -1511,6 +1513,7 @@ static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWO ...@@ -1511,6 +1513,7 @@ static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWO
{ {
struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface); struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface);
struct wined3d_rendertarget_view *rtv;
HRESULT hr; HRESULT hr;
TRACE("iface %p, idx %u, surface %p.\n", iface, idx, surface); TRACE("iface %p, idx %u, surface %p.\n", iface, idx, surface);
...@@ -1534,8 +1537,9 @@ static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWO ...@@ -1534,8 +1537,9 @@ static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWO
} }
wined3d_mutex_lock(); wined3d_mutex_lock();
hr = wined3d_device_set_rendertarget_view(device->wined3d_device, idx, rtv = surface_impl ? d3d9_surface_acquire_rendertarget_view(surface_impl) : NULL;
surface_impl ? d3d9_surface_get_rendertarget_view(surface_impl) : NULL, TRUE); hr = wined3d_device_set_rendertarget_view(device->wined3d_device, idx, rtv, TRUE);
d3d9_surface_release_rendertarget_view(surface_impl, rtv);
wined3d_mutex_unlock(); wined3d_mutex_unlock();
return hr; return hr;
...@@ -1582,12 +1586,14 @@ static HRESULT WINAPI d3d9_device_SetDepthStencilSurface(IDirect3DDevice9Ex *ifa ...@@ -1582,12 +1586,14 @@ static HRESULT WINAPI d3d9_device_SetDepthStencilSurface(IDirect3DDevice9Ex *ifa
{ {
struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
struct d3d9_surface *ds_impl = unsafe_impl_from_IDirect3DSurface9(depth_stencil); 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); TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
wined3d_mutex_lock(); wined3d_mutex_lock();
wined3d_device_set_depth_stencil_view(device->wined3d_device, rtv = ds_impl ? d3d9_surface_acquire_rendertarget_view(ds_impl) : NULL;
ds_impl ? d3d9_surface_get_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(); wined3d_mutex_unlock();
return D3D_OK; return D3D_OK;
......
...@@ -396,10 +396,15 @@ struct d3d9_device *d3d9_surface_get_device(const struct d3d9_surface *surface) ...@@ -396,10 +396,15 @@ struct d3d9_device *d3d9_surface_get_device(const struct d3d9_surface *surface)
return impl_from_IDirect3DDevice9Ex(device); 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; 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) if (surface->wined3d_rtv)
return surface->wined3d_rtv; return surface->wined3d_rtv;
...@@ -407,6 +412,7 @@ struct wined3d_rendertarget_view *d3d9_surface_get_rendertarget_view(struct d3d9 ...@@ -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))) surface->sub_resource_idx, surface, &d3d9_view_wined3d_parent_ops, &surface->wined3d_rtv)))
{ {
ERR("Failed to create rendertarget view, hr %#x.\n", hr); ERR("Failed to create rendertarget view, hr %#x.\n", hr);
d3d9_surface_Release(&surface->IDirect3DSurface9_iface);
return NULL; return NULL;
} }
...@@ -416,6 +422,13 @@ struct wined3d_rendertarget_view *d3d9_surface_get_rendertarget_view(struct d3d9 ...@@ -416,6 +422,13 @@ struct wined3d_rendertarget_view *d3d9_surface_get_rendertarget_view(struct d3d9
return surface->wined3d_rtv; 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) struct d3d9_surface *unsafe_impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface)
{ {
if (!iface) if (!iface)
......
...@@ -22223,7 +22223,6 @@ static void test_max_index16(void) ...@@ -22223,7 +22223,6 @@ static void test_max_index16(void)
DestroyWindow(window); DestroyWindow(window);
} }
/* This test exercises a regression in Wine d3d9 implementation. */
static void test_backbuffer_resize(void) static void test_backbuffer_resize(void)
{ {
D3DPRESENT_PARAMETERS present_parameters = {0}; D3DPRESENT_PARAMETERS present_parameters = {0};
...@@ -22257,8 +22256,8 @@ static void test_backbuffer_resize(void) ...@@ -22257,8 +22256,8 @@ static void test_backbuffer_resize(void)
goto done; goto done;
} }
/* In order to exercise the regression the backbuffer surface has to be /* Wine d3d9 implementation had a bug which was triggered by a
* unreferenced when SetRenderTarget() is called. */ * SetRenderTarget() call with an unreferenced surface. */
hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr); ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
refcount = IDirect3DSurface9_Release(backbuffer); refcount = IDirect3DSurface9_Release(backbuffer);
...@@ -22304,7 +22303,7 @@ static void test_backbuffer_resize(void) ...@@ -22304,7 +22303,7 @@ static void test_backbuffer_resize(void)
color = getPixelColor(device, 1, 1); color = getPixelColor(device, 1, 1);
ok(color == 0x00ffff00, "Got unexpected color 0x%08x.\n", color); ok(color == 0x00ffff00, "Got unexpected color 0x%08x.\n", color);
color = getPixelColor(device, 700, 500); 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); hr = IDirect3DDevice9_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
...@@ -22315,7 +22314,7 @@ static void test_backbuffer_resize(void) ...@@ -22315,7 +22314,7 @@ static void test_backbuffer_resize(void)
color = getPixelColor(device, 1, 1); color = getPixelColor(device, 1, 1);
ok(color == 0x0000ff00, "Got unexpected color 0x%08x.\n", color); ok(color == 0x0000ff00, "Got unexpected color 0x%08x.\n", color);
color = getPixelColor(device, 700, 500); 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); refcount = IDirect3DDevice9_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount); ok(!refcount, "Device has %u references left.\n", refcount);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment