d3d9: Do not create render target view while surface refcount is equal to 0.
This fixes a regression introduced by commit
b005ad6f90
.
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@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
da5a0b7611
commit
e8360b8eaa
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue