d3d8: Do not create render target view while surface refcount is equal to 0.
This fixes a regression introduced by commit
b005ad6f90
.
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
e8360b8eaa
commit
62f43eeb02
|
@ -242,8 +242,10 @@ struct d3d8_surface
|
||||||
struct d3d8_texture *texture;
|
struct d3d8_texture *texture;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct wined3d_rendertarget_view *d3d8_surface_acquire_rendertarget_view(struct d3d8_surface *surface) DECLSPEC_HIDDEN;
|
||||||
struct d3d8_device *d3d8_surface_get_device(const struct d3d8_surface *surface) DECLSPEC_HIDDEN;
|
struct d3d8_device *d3d8_surface_get_device(const struct d3d8_surface *surface) DECLSPEC_HIDDEN;
|
||||||
struct wined3d_rendertarget_view *d3d8_surface_get_rendertarget_view(struct d3d8_surface *surface) DECLSPEC_HIDDEN;
|
void d3d8_surface_release_rendertarget_view(struct d3d8_surface *surface,
|
||||||
|
struct wined3d_rendertarget_view *rtv) DECLSPEC_HIDDEN;
|
||||||
void surface_init(struct d3d8_surface *surface, struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
|
void surface_init(struct d3d8_surface *surface, struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
|
||||||
const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
|
const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
|
||||||
struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface) DECLSPEC_HIDDEN;
|
struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -1156,7 +1156,7 @@ static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
|
||||||
struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
|
struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
|
||||||
struct d3d8_surface *rt_impl = unsafe_impl_from_IDirect3DSurface8(render_target);
|
struct d3d8_surface *rt_impl = unsafe_impl_from_IDirect3DSurface8(render_target);
|
||||||
struct d3d8_surface *ds_impl = unsafe_impl_from_IDirect3DSurface8(depth_stencil);
|
struct d3d8_surface *ds_impl = unsafe_impl_from_IDirect3DSurface8(depth_stencil);
|
||||||
struct wined3d_rendertarget_view *original_dsv;
|
struct wined3d_rendertarget_view *original_dsv, *rtv;
|
||||||
HRESULT hr = D3D_OK;
|
HRESULT hr = D3D_OK;
|
||||||
|
|
||||||
TRACE("iface %p, render_target %p, depth_stencil %p.\n", iface, render_target, depth_stencil);
|
TRACE("iface %p, render_target %p, depth_stencil %p.\n", iface, render_target, depth_stencil);
|
||||||
|
@ -1178,7 +1178,6 @@ static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
|
||||||
/* If no render target is passed in check the size against the current RT */
|
/* If no render target is passed in check the size against the current RT */
|
||||||
if (!render_target)
|
if (!render_target)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!(original_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
|
if (!(original_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
|
||||||
{
|
{
|
||||||
wined3d_mutex_unlock();
|
wined3d_mutex_unlock();
|
||||||
|
@ -1210,11 +1209,13 @@ static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
|
||||||
}
|
}
|
||||||
|
|
||||||
original_dsv = wined3d_device_get_depth_stencil_view(device->wined3d_device);
|
original_dsv = wined3d_device_get_depth_stencil_view(device->wined3d_device);
|
||||||
wined3d_device_set_depth_stencil_view(device->wined3d_device,
|
rtv = ds_impl ? d3d8_surface_acquire_rendertarget_view(ds_impl) : NULL;
|
||||||
ds_impl ? d3d8_surface_get_rendertarget_view(ds_impl) : NULL);
|
wined3d_device_set_depth_stencil_view(device->wined3d_device, rtv);
|
||||||
if (render_target && FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device, 0,
|
d3d8_surface_release_rendertarget_view(ds_impl, rtv);
|
||||||
d3d8_surface_get_rendertarget_view(rt_impl), TRUE)))
|
rtv = render_target ? d3d8_surface_acquire_rendertarget_view(rt_impl) : NULL;
|
||||||
|
if (render_target && FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device, 0, rtv, TRUE)))
|
||||||
wined3d_device_set_depth_stencil_view(device->wined3d_device, original_dsv);
|
wined3d_device_set_depth_stencil_view(device->wined3d_device, original_dsv);
|
||||||
|
d3d8_surface_release_rendertarget_view(rt_impl, rtv);
|
||||||
|
|
||||||
wined3d_mutex_unlock();
|
wined3d_mutex_unlock();
|
||||||
|
|
||||||
|
|
|
@ -360,10 +360,15 @@ struct d3d8_device *d3d8_surface_get_device(const struct d3d8_surface *surface)
|
||||||
return impl_from_IDirect3DDevice8(device);
|
return impl_from_IDirect3DDevice8(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wined3d_rendertarget_view *d3d8_surface_get_rendertarget_view(struct d3d8_surface *surface)
|
struct wined3d_rendertarget_view *d3d8_surface_acquire_rendertarget_view(struct d3d8_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. */
|
||||||
|
d3d8_surface_AddRef(&surface->IDirect3DSurface8_iface);
|
||||||
|
|
||||||
if (surface->wined3d_rtv)
|
if (surface->wined3d_rtv)
|
||||||
return surface->wined3d_rtv;
|
return surface->wined3d_rtv;
|
||||||
|
|
||||||
|
@ -371,6 +376,7 @@ struct wined3d_rendertarget_view *d3d8_surface_get_rendertarget_view(struct d3d8
|
||||||
surface->sub_resource_idx, surface, &d3d8_view_wined3d_parent_ops, &surface->wined3d_rtv)))
|
surface->sub_resource_idx, surface, &d3d8_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);
|
||||||
|
d3d8_surface_Release(&surface->IDirect3DSurface8_iface);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,6 +386,13 @@ struct wined3d_rendertarget_view *d3d8_surface_get_rendertarget_view(struct d3d8
|
||||||
return surface->wined3d_rtv;
|
return surface->wined3d_rtv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void d3d8_surface_release_rendertarget_view(struct d3d8_surface *surface,
|
||||||
|
struct wined3d_rendertarget_view *rtv)
|
||||||
|
{
|
||||||
|
if (rtv)
|
||||||
|
d3d8_surface_Release(&surface->IDirect3DSurface8_iface);
|
||||||
|
}
|
||||||
|
|
||||||
struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface)
|
struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface)
|
||||||
{
|
{
|
||||||
if (!iface)
|
if (!iface)
|
||||||
|
|
|
@ -9684,7 +9684,6 @@ static void test_max_index16(void)
|
||||||
DestroyWindow(window);
|
DestroyWindow(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This test exercises a regression in Wine d3d8 implementation. */
|
|
||||||
static void test_backbuffer_resize(void)
|
static void test_backbuffer_resize(void)
|
||||||
{
|
{
|
||||||
D3DPRESENT_PARAMETERS present_parameters = {0};
|
D3DPRESENT_PARAMETERS present_parameters = {0};
|
||||||
|
@ -9719,8 +9718,8 @@ static void test_backbuffer_resize(void)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In order to exercise the regression the backbuffer surface has to be
|
/* Wine d3d8 implementation had a bug which was triggered by a
|
||||||
* unreferenced when SetRenderTarget() is called. */
|
* SetRenderTarget() call with an unreferenced surface. */
|
||||||
hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
|
hr = IDirect3DDevice8_GetBackBuffer(device, 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 = IDirect3DSurface8_Release(backbuffer);
|
refcount = IDirect3DSurface8_Release(backbuffer);
|
||||||
|
@ -9766,7 +9765,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 = IDirect3DDevice8_BeginScene(device);
|
hr = IDirect3DDevice8_BeginScene(device);
|
||||||
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
|
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
|
||||||
|
@ -9777,7 +9776,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 = IDirect3DDevice8_Release(device);
|
refcount = IDirect3DDevice8_Release(device);
|
||||||
ok(!refcount, "Device has %u references left.\n", refcount);
|
ok(!refcount, "Device has %u references left.\n", refcount);
|
||||||
|
|
Loading…
Reference in New Issue