[PATCH 5/5] wined3d: Use rendertarget views for color output instead of surfaces.
Henri Verbeet
hverbeet at codeweavers.com
Thu Aug 21 02:55:55 CDT 2014
---
dlls/d3d10core/d3d10core_private.h | 2 +
dlls/d3d10core/view.c | 3 +-
dlls/d3d8/d3d8_private.h | 4 ++
dlls/d3d8/device.c | 26 ++++----
dlls/d3d8/surface.c | 47 ++++++++++++++
dlls/d3d8/texture.c | 25 ++++++++
dlls/d3d9/d3d9_private.h | 4 ++
dlls/d3d9/device.c | 12 ++--
dlls/d3d9/surface.c | 47 ++++++++++++++
dlls/d3d9/texture.c | 25 ++++++++
dlls/ddraw/ddraw.c | 20 +++---
dlls/ddraw/ddraw_private.h | 2 +
dlls/ddraw/device.c | 10 +--
dlls/ddraw/surface.c | 68 +++++++++++++++++---
dlls/wined3d/arb_program_shader.c | 4 +-
dlls/wined3d/context.c | 47 ++++++++------
dlls/wined3d/cs.c | 28 ++++----
dlls/wined3d/device.c | 123 ++++++++++++++++++++++--------------
dlls/wined3d/drawprim.c | 4 +-
dlls/wined3d/glsl_shader.c | 2 +-
dlls/wined3d/shader.c | 4 +-
dlls/wined3d/state.c | 35 +++++-----
dlls/wined3d/surface.c | 34 ++++++----
dlls/wined3d/texture.c | 4 +-
dlls/wined3d/utils.c | 4 +-
dlls/wined3d/view.c | 50 ++++++++++++++-
dlls/wined3d/wined3d.spec | 9 ++-
dlls/wined3d/wined3d_private.h | 33 ++++++++--
include/wine/wined3d.h | 15 +++--
29 files changed, 512 insertions(+), 179 deletions(-)
diff --git a/dlls/d3d10core/d3d10core_private.h b/dlls/d3d10core/d3d10core_private.h
index a697a0e..8497f3a 100644
--- a/dlls/d3d10core/d3d10core_private.h
+++ b/dlls/d3d10core/d3d10core_private.h
@@ -53,6 +53,8 @@ struct d3d10_shader_info
struct wined3d_shader_signature *output_signature;
};
+extern const struct wined3d_parent_ops d3d10_null_wined3d_parent_ops DECLSPEC_HIDDEN;
+
/* TRACE helper functions */
const char *debug_d3d10_primitive_topology(D3D10_PRIMITIVE_TOPOLOGY topology) DECLSPEC_HIDDEN;
const char *debug_dxgi_format(DXGI_FORMAT format) DECLSPEC_HIDDEN;
diff --git a/dlls/d3d10core/view.c b/dlls/d3d10core/view.c
index 7394466..fb69f51 100644
--- a/dlls/d3d10core/view.c
+++ b/dlls/d3d10core/view.c
@@ -745,7 +745,8 @@ HRESULT d3d10_rendertarget_view_init(struct d3d10_rendertarget_view *view, struc
}
wined3d_rendertarget_view_desc_from_d3d10core(&wined3d_desc, &view->desc);
- if (FAILED(hr = wined3d_rendertarget_view_create(&wined3d_desc, wined3d_resource, view, &view->wined3d_view)))
+ if (FAILED(hr = wined3d_rendertarget_view_create(&wined3d_desc, wined3d_resource,
+ view, &d3d10_null_wined3d_parent_ops, &view->wined3d_view)))
{
WARN("Failed to create a wined3d rendertarget view, hr %#x.\n", hr);
return hr;
diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h
index 74f96ef..6283c8d 100644
--- a/dlls/d3d8/d3d8_private.h
+++ b/dlls/d3d8/d3d8_private.h
@@ -227,11 +227,14 @@ struct d3d8_surface
IDirect3DSurface8 IDirect3DSurface8_iface;
struct d3d8_resource resource;
struct wined3d_surface *wined3d_surface;
+ struct list rtv_entry;
+ struct wined3d_rendertarget_view *wined3d_rtv;
IDirect3DDevice8 *parent_device;
IUnknown *container;
struct d3d8_texture *texture;
};
+struct wined3d_rendertarget_view *d3d8_surface_get_rendertarget_view(struct d3d8_surface *surface) DECLSPEC_HIDDEN;
void surface_init(struct d3d8_surface *surface, IUnknown *container_parent,
struct wined3d_surface *wined3d_surface, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface) DECLSPEC_HIDDEN;
@@ -268,6 +271,7 @@ struct d3d8_texture
struct d3d8_resource resource;
struct wined3d_texture *wined3d_texture;
IDirect3DDevice8 *parent_device;
+ struct list rtv_list;
};
HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *device,
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index 8458583..3eaa948 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -1136,19 +1136,22 @@ static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
if (ds_impl)
{
+ struct wined3d_rendertarget_view *original_rtv;
struct wined3d_resource_desc ds_desc, rt_desc;
struct wined3d_resource *wined3d_resource;
- struct wined3d_surface *original_rt = NULL;
+ struct d3d8_surface *original_surface;
/* If no render target is passed in check the size against the current RT */
if (!render_target)
{
- if (!(original_rt = wined3d_device_get_render_target(device->wined3d_device, 0)))
+
+ if (!(original_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
{
wined3d_mutex_unlock();
return D3DERR_NOTFOUND;
}
- wined3d_resource = wined3d_surface_get_resource(original_rt);
+ original_surface = wined3d_rendertarget_view_get_sub_resource_parent(original_rtv);
+ wined3d_resource = wined3d_surface_get_resource(original_surface->wined3d_surface);
}
else
wined3d_resource = wined3d_surface_get_resource(rt_impl->wined3d_surface);
@@ -1167,12 +1170,9 @@ static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
original_ds = wined3d_device_get_depth_stencil(device->wined3d_device);
wined3d_device_set_depth_stencil(device->wined3d_device, ds_impl ? ds_impl->wined3d_surface : NULL);
- if (render_target)
- {
- hr = wined3d_device_set_render_target(device->wined3d_device, 0, rt_impl->wined3d_surface, TRUE);
- if (FAILED(hr))
- wined3d_device_set_depth_stencil(device->wined3d_device, original_ds);
- }
+ if (render_target && FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device, 0,
+ d3d8_surface_get_rendertarget_view(rt_impl), TRUE)))
+ wined3d_device_set_depth_stencil(device->wined3d_device, original_ds);
wined3d_mutex_unlock();
@@ -1182,7 +1182,7 @@ static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
static HRESULT WINAPI d3d8_device_GetRenderTarget(IDirect3DDevice8 *iface, IDirect3DSurface8 **render_target)
{
struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
- struct wined3d_surface *wined3d_surface;
+ struct wined3d_rendertarget_view *wined3d_rtv;
struct d3d8_surface *surface_impl;
HRESULT hr;
@@ -1192,9 +1192,11 @@ static HRESULT WINAPI d3d8_device_GetRenderTarget(IDirect3DDevice8 *iface, IDire
return D3DERR_INVALIDCALL;
wined3d_mutex_lock();
- if ((wined3d_surface = wined3d_device_get_render_target(device->wined3d_device, 0)))
+ if ((wined3d_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
{
- surface_impl = wined3d_surface_get_parent(wined3d_surface);
+ /* We want the sub resource parent here, since the view itself may be
+ * internal to wined3d and may not have a parent. */
+ surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_rtv);
*render_target = &surface_impl->IDirect3DSurface8_iface;
IDirect3DSurface8_AddRef(*render_target);
hr = D3D_OK;
diff --git a/dlls/d3d8/surface.c b/dlls/d3d8/surface.c
index d20d791..7779a56 100644
--- a/dlls/d3d8/surface.c
+++ b/dlls/d3d8/surface.c
@@ -68,6 +68,8 @@ static ULONG WINAPI d3d8_surface_AddRef(IDirect3DSurface8 *iface)
if (surface->parent_device)
IDirect3DDevice8_AddRef(surface->parent_device);
wined3d_mutex_lock();
+ if (surface->wined3d_rtv)
+ wined3d_rendertarget_view_incref(surface->wined3d_rtv);
wined3d_surface_incref(surface->wined3d_surface);
wined3d_mutex_unlock();
}
@@ -96,6 +98,8 @@ static ULONG WINAPI d3d8_surface_Release(IDirect3DSurface8 *iface)
IDirect3DDevice8 *parent_device = surface->parent_device;
wined3d_mutex_lock();
+ if (surface->wined3d_rtv)
+ wined3d_rendertarget_view_decref(surface->wined3d_rtv);
wined3d_surface_decref(surface->wined3d_surface);
wined3d_mutex_unlock();
@@ -297,6 +301,7 @@ void surface_init(struct d3d8_surface *surface, IUnknown *container_parent,
d3d8_resource_init(&surface->resource);
surface->resource.refcount = 0;
surface->wined3d_surface = wined3d_surface;
+ list_init(&surface->rtv_entry);
surface->container = container_parent;
if (container_parent && SUCCEEDED(IUnknown_QueryInterface(container_parent,
@@ -309,6 +314,48 @@ void surface_init(struct d3d8_surface *surface, IUnknown *container_parent,
*parent_ops = &d3d8_surface_wined3d_parent_ops;
}
+static void STDMETHODCALLTYPE view_wined3d_object_destroyed(void *parent)
+{
+ struct d3d8_surface *surface = parent;
+
+ /* If the surface reference count drops to zero, we release our reference
+ * to the view, but don't clear the pointer yet, in case e.g. a
+ * GetRenderTarget() call brings the surface back before the view is
+ * actually destroyed. When the view is destroyed, we need to clear the
+ * pointer, or a subsequent surface AddRef() would reference it again.
+ *
+ * This is safe because as long as the view still has a reference to the
+ * texture, the surface is also still alive, and we're called before the
+ * view releases that reference. */
+ surface->wined3d_rtv = NULL;
+ list_remove(&surface->rtv_entry);
+}
+
+static const struct wined3d_parent_ops d3d8_view_wined3d_parent_ops =
+{
+ view_wined3d_object_destroyed,
+};
+
+struct wined3d_rendertarget_view *d3d8_surface_get_rendertarget_view(struct d3d8_surface *surface)
+{
+ HRESULT hr;
+
+ if (surface->wined3d_rtv)
+ return surface->wined3d_rtv;
+
+ if (FAILED(hr = wined3d_rendertarget_view_create_from_surface(surface->wined3d_surface,
+ surface, &d3d8_view_wined3d_parent_ops, &surface->wined3d_rtv)))
+ {
+ ERR("Failed to create rendertarget view, hr %#x.\n", hr);
+ return NULL;
+ }
+
+ if (surface->texture)
+ list_add_head(&surface->texture->rtv_list, &surface->rtv_entry);
+
+ return surface->wined3d_rtv;
+}
+
struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface)
{
if (!iface)
diff --git a/dlls/d3d8/texture.c b/dlls/d3d8/texture.c
index 1cdf97b..54944ac 100644
--- a/dlls/d3d8/texture.c
+++ b/dlls/d3d8/texture.c
@@ -65,8 +65,14 @@ static ULONG WINAPI d3d8_texture_2d_AddRef(IDirect3DTexture8 *iface)
if (ref == 1)
{
+ struct d3d8_surface *surface;
+
IDirect3DDevice8_AddRef(texture->parent_device);
wined3d_mutex_lock();
+ LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d8_surface, rtv_entry)
+ {
+ wined3d_rendertarget_view_incref(surface->wined3d_rtv);
+ }
wined3d_texture_incref(texture->wined3d_texture);
wined3d_mutex_unlock();
}
@@ -84,8 +90,13 @@ static ULONG WINAPI d3d8_texture_2d_Release(IDirect3DTexture8 *iface)
if (!ref)
{
IDirect3DDevice8 *parent_device = texture->parent_device;
+ struct d3d8_surface *surface;
wined3d_mutex_lock();
+ LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d8_surface, rtv_entry)
+ {
+ wined3d_rendertarget_view_decref(surface->wined3d_rtv);
+ }
wined3d_texture_decref(texture->wined3d_texture);
wined3d_mutex_unlock();
@@ -413,8 +424,14 @@ static ULONG WINAPI d3d8_texture_cube_AddRef(IDirect3DCubeTexture8 *iface)
if (ref == 1)
{
+ struct d3d8_surface *surface;
+
IDirect3DDevice8_AddRef(texture->parent_device);
wined3d_mutex_lock();
+ LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d8_surface, rtv_entry)
+ {
+ wined3d_rendertarget_view_incref(surface->wined3d_rtv);
+ }
wined3d_texture_incref(texture->wined3d_texture);
wined3d_mutex_unlock();
}
@@ -432,10 +449,15 @@ static ULONG WINAPI d3d8_texture_cube_Release(IDirect3DCubeTexture8 *iface)
if (!ref)
{
IDirect3DDevice8 *parent_device = texture->parent_device;
+ struct d3d8_surface *surface;
TRACE("Releasing child %p.\n", texture->wined3d_texture);
wined3d_mutex_lock();
+ LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d8_surface, rtv_entry)
+ {
+ wined3d_rendertarget_view_decref(surface->wined3d_rtv);
+ }
wined3d_texture_decref(texture->wined3d_texture);
wined3d_mutex_unlock();
@@ -1133,6 +1155,7 @@ HRESULT texture_init(struct d3d8_texture *texture, struct d3d8_device *device,
texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DTexture8_Vtbl;
d3d8_resource_init(&texture->resource);
+ list_init(&texture->rtv_list);
desc.resource_type = WINED3D_RTYPE_TEXTURE;
desc.format = wined3dformat_from_d3dformat(format);
@@ -1174,6 +1197,7 @@ HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *devic
texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DCubeTexture8_Vtbl;
d3d8_resource_init(&texture->resource);
+ list_init(&texture->rtv_list);
desc.resource_type = WINED3D_RTYPE_CUBE_TEXTURE;
desc.format = wined3dformat_from_d3dformat(format);
@@ -1214,6 +1238,7 @@ HRESULT volumetexture_init(struct d3d8_texture *texture, struct d3d8_device *dev
texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DVolumeTexture8_Vtbl;
d3d8_resource_init(&texture->resource);
+ list_init(&texture->rtv_list);
desc.resource_type = WINED3D_RTYPE_VOLUME_TEXTURE;
desc.format = wined3dformat_from_d3dformat(format);
diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
index bde8583..d12805f 100644
--- a/dlls/d3d9/d3d9_private.h
+++ b/dlls/d3d9/d3d9_private.h
@@ -214,12 +214,15 @@ struct d3d9_surface
IDirect3DSurface9 IDirect3DSurface9_iface;
struct d3d9_resource resource;
struct wined3d_surface *wined3d_surface;
+ struct list rtv_entry;
+ struct wined3d_rendertarget_view *wined3d_rtv;
IDirect3DDevice9Ex *parent_device;
IUnknown *container;
struct d3d9_texture *texture;
BOOL getdc_supported;
};
+struct wined3d_rendertarget_view *d3d9_surface_get_rendertarget_view(struct d3d9_surface *surface) DECLSPEC_HIDDEN;
void surface_init(struct d3d9_surface *surface, IUnknown *container_parent,
struct wined3d_surface *wined3d_surface, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
struct d3d9_surface *unsafe_impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface) DECLSPEC_HIDDEN;
@@ -256,6 +259,7 @@ struct d3d9_texture
struct d3d9_resource resource;
struct wined3d_texture *wined3d_texture;
IDirect3DDevice9Ex *parent_device;
+ struct list rtv_list;
};
HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *device,
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index 7d41e4e..6dfd600 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -1345,8 +1345,8 @@ static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWO
}
wined3d_mutex_lock();
- hr = wined3d_device_set_render_target(device->wined3d_device, idx,
- surface_impl ? surface_impl->wined3d_surface : NULL, TRUE);
+ hr = wined3d_device_set_rendertarget_view(device->wined3d_device, idx,
+ surface_impl ? d3d9_surface_get_rendertarget_view(surface_impl) : NULL, TRUE);
wined3d_mutex_unlock();
return hr;
@@ -1355,7 +1355,7 @@ static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWO
static HRESULT WINAPI d3d9_device_GetRenderTarget(IDirect3DDevice9Ex *iface, DWORD idx, IDirect3DSurface9 **surface)
{
struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
- struct wined3d_surface *wined3d_surface;
+ struct wined3d_rendertarget_view *wined3d_rtv;
struct d3d9_surface *surface_impl;
HRESULT hr = D3D_OK;
@@ -1371,9 +1371,11 @@ static HRESULT WINAPI d3d9_device_GetRenderTarget(IDirect3DDevice9Ex *iface, DWO
}
wined3d_mutex_lock();
- if ((wined3d_surface = wined3d_device_get_render_target(device->wined3d_device, idx)))
+ if ((wined3d_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, idx)))
{
- surface_impl = wined3d_surface_get_parent(wined3d_surface);
+ /* We want the sub resource parent here, since the view itself may be
+ * internal to wined3d and may not have a parent. */
+ surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_rtv);
*surface = &surface_impl->IDirect3DSurface9_iface;
IDirect3DSurface9_AddRef(*surface);
}
diff --git a/dlls/d3d9/surface.c b/dlls/d3d9/surface.c
index 17f2ace..e5eb11f 100644
--- a/dlls/d3d9/surface.c
+++ b/dlls/d3d9/surface.c
@@ -69,6 +69,8 @@ static ULONG WINAPI d3d9_surface_AddRef(IDirect3DSurface9 *iface)
if (surface->parent_device)
IDirect3DDevice9Ex_AddRef(surface->parent_device);
wined3d_mutex_lock();
+ if (surface->wined3d_rtv)
+ wined3d_rendertarget_view_incref(surface->wined3d_rtv);
wined3d_surface_incref(surface->wined3d_surface);
wined3d_mutex_unlock();
}
@@ -97,6 +99,8 @@ static ULONG WINAPI d3d9_surface_Release(IDirect3DSurface9 *iface)
IDirect3DDevice9Ex *parent_device = surface->parent_device;
wined3d_mutex_lock();
+ if (surface->wined3d_rtv)
+ wined3d_rendertarget_view_decref(surface->wined3d_rtv);
wined3d_surface_decref(surface->wined3d_surface);
wined3d_mutex_unlock();
@@ -351,6 +355,7 @@ void surface_init(struct d3d9_surface *surface, IUnknown *container_parent,
d3d9_resource_init(&surface->resource);
surface->resource.refcount = 0;
surface->wined3d_surface = wined3d_surface;
+ list_init(&surface->rtv_entry);
surface->container = container_parent;
if (container_parent && SUCCEEDED(IUnknown_QueryInterface(container_parent,
@@ -380,6 +385,48 @@ void surface_init(struct d3d9_surface *surface, IUnknown *container_parent,
*parent_ops = &d3d9_surface_wined3d_parent_ops;
}
+static void STDMETHODCALLTYPE view_wined3d_object_destroyed(void *parent)
+{
+ struct d3d9_surface *surface = parent;
+
+ /* If the surface reference count drops to zero, we release our reference
+ * to the view, but don't clear the pointer yet, in case e.g. a
+ * GetRenderTarget() call brings the surface back before the view is
+ * actually destroyed. When the view is destroyed, we need to clear the
+ * pointer, or a subsequent surface AddRef() would reference it again.
+ *
+ * This is safe because as long as the view still has a reference to the
+ * texture, the surface is also still alive, and we're called before the
+ * view releases that reference. */
+ surface->wined3d_rtv = NULL;
+ list_remove(&surface->rtv_entry);
+}
+
+static const struct wined3d_parent_ops d3d9_view_wined3d_parent_ops =
+{
+ view_wined3d_object_destroyed,
+};
+
+struct wined3d_rendertarget_view *d3d9_surface_get_rendertarget_view(struct d3d9_surface *surface)
+{
+ HRESULT hr;
+
+ if (surface->wined3d_rtv)
+ return surface->wined3d_rtv;
+
+ if (FAILED(hr = wined3d_rendertarget_view_create_from_surface(surface->wined3d_surface,
+ surface, &d3d9_view_wined3d_parent_ops, &surface->wined3d_rtv)))
+ {
+ ERR("Failed to create rendertarget view, hr %#x.\n", hr);
+ return NULL;
+ }
+
+ if (surface->texture)
+ list_add_head(&surface->texture->rtv_list, &surface->rtv_entry);
+
+ return surface->wined3d_rtv;
+}
+
struct d3d9_surface *unsafe_impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface)
{
if (!iface)
diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c
index a57ecb1..432d248 100644
--- a/dlls/d3d9/texture.c
+++ b/dlls/d3d9/texture.c
@@ -67,8 +67,14 @@ static ULONG WINAPI d3d9_texture_2d_AddRef(IDirect3DTexture9 *iface)
if (ref == 1)
{
+ struct d3d9_surface *surface;
+
IDirect3DDevice9Ex_AddRef(texture->parent_device);
wined3d_mutex_lock();
+ LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry)
+ {
+ wined3d_rendertarget_view_incref(surface->wined3d_rtv);
+ }
wined3d_texture_incref(texture->wined3d_texture);
wined3d_mutex_unlock();
}
@@ -86,8 +92,13 @@ static ULONG WINAPI d3d9_texture_2d_Release(IDirect3DTexture9 *iface)
if (!ref)
{
IDirect3DDevice9Ex *parent_device = texture->parent_device;
+ struct d3d9_surface *surface;
wined3d_mutex_lock();
+ LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry)
+ {
+ wined3d_rendertarget_view_decref(surface->wined3d_rtv);
+ }
wined3d_texture_decref(texture->wined3d_texture);
wined3d_mutex_unlock();
@@ -458,8 +469,14 @@ static ULONG WINAPI d3d9_texture_cube_AddRef(IDirect3DCubeTexture9 *iface)
if (ref == 1)
{
+ struct d3d9_surface *surface;
+
IDirect3DDevice9Ex_AddRef(texture->parent_device);
wined3d_mutex_lock();
+ LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry)
+ {
+ wined3d_rendertarget_view_decref(surface->wined3d_rtv);
+ }
wined3d_texture_incref(texture->wined3d_texture);
wined3d_mutex_unlock();
}
@@ -477,10 +494,15 @@ static ULONG WINAPI d3d9_texture_cube_Release(IDirect3DCubeTexture9 *iface)
if (!ref)
{
IDirect3DDevice9Ex *parent_device = texture->parent_device;
+ struct d3d9_surface *surface;
TRACE("Releasing child %p.\n", texture->wined3d_texture);
wined3d_mutex_lock();
+ LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry)
+ {
+ wined3d_rendertarget_view_decref(surface->wined3d_rtv);
+ }
wined3d_texture_decref(texture->wined3d_texture);
wined3d_mutex_unlock();
@@ -1257,6 +1279,7 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device,
texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_2d_vtbl;
d3d9_resource_init(&texture->resource);
+ list_init(&texture->rtv_list);
desc.resource_type = WINED3D_RTYPE_TEXTURE;
desc.format = wined3dformat_from_d3dformat(format);
@@ -1298,6 +1321,7 @@ HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *devic
texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_cube_vtbl;
d3d9_resource_init(&texture->resource);
+ list_init(&texture->rtv_list);
desc.resource_type = WINED3D_RTYPE_CUBE_TEXTURE;
desc.format = wined3dformat_from_d3dformat(format);
@@ -1338,6 +1362,7 @@ HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *dev
texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_3d_vtbl;
d3d9_resource_init(&texture->resource);
+ list_init(&texture->rtv_list);
desc.resource_type = WINED3D_RTYPE_VOLUME_TEXTURE;
desc.format = wined3dformat_from_d3dformat(format);
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index 5f0070a..0af90d8 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -767,8 +767,9 @@ static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface)
static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
DWORD cooplevel, BOOL restore_mode_on_normal)
{
- struct wined3d_surface *rt = NULL, *ds = NULL;
+ struct wined3d_rendertarget_view *rtv = NULL;
struct wined3d_stateblock *stateblock;
+ struct wined3d_surface *ds = NULL;
BOOL restore_state = FALSE;
HRESULT hr;
@@ -918,11 +919,12 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
}
wined3d_stateblock_capture(stateblock);
- rt = wined3d_device_get_render_target(ddraw->wined3d_device, 0);
- if (rt == ddraw->wined3d_frontbuffer)
- rt = NULL;
- else if (rt)
- wined3d_surface_incref(rt);
+ rtv = wined3d_device_get_rendertarget_view(ddraw->wined3d_device, 0);
+ /* Rendering to ddraw->wined3d_frontbuffer. */
+ if (rtv && !wined3d_rendertarget_view_get_sub_resource_parent(rtv))
+ rtv = NULL;
+ else if (rtv)
+ wined3d_rendertarget_view_incref(rtv);
if ((ds = wined3d_device_get_depth_stencil(ddraw->wined3d_device)))
wined3d_surface_incref(ds);
@@ -942,10 +944,10 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
wined3d_surface_decref(ds);
}
- if (rt)
+ if (rtv)
{
- wined3d_device_set_render_target(ddraw->wined3d_device, 0, rt, FALSE);
- wined3d_surface_decref(rt);
+ wined3d_device_set_rendertarget_view(ddraw->wined3d_device, 0, rtv, FALSE);
+ wined3d_rendertarget_view_decref(rtv);
}
wined3d_stateblock_apply(stateblock);
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index 374c273..7d028dd 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -158,6 +158,7 @@ struct ddraw_surface
struct ddraw *ddraw;
struct wined3d_surface *wined3d_surface;
struct wined3d_texture *wined3d_texture;
+ struct wined3d_rendertarget_view *wined3d_rtv;
struct wined3d_private_store private_store;
struct d3d_device *device1;
@@ -205,6 +206,7 @@ struct ddraw_texture
HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc,
struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version) DECLSPEC_HIDDEN;
+struct wined3d_rendertarget_view *ddraw_surface_get_rendertarget_view(struct ddraw_surface *surface) DECLSPEC_HIDDEN;
HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, struct ddraw_texture *texture,
struct wined3d_surface *wined3d_surface, const struct wined3d_parent_ops **parent_ops) DECLSPEC_HIDDEN;
ULONG ddraw_surface_release_iface(struct ddraw_surface *This) DECLSPEC_HIDDEN;
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c
index 4f270fd..456e7e8 100644
--- a/dlls/ddraw/device.c
+++ b/dlls/ddraw/device.c
@@ -246,7 +246,7 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface)
if (This->vertex_buffer)
wined3d_buffer_decref(This->vertex_buffer);
- wined3d_device_set_render_target(This->wined3d_device, 0, NULL, FALSE);
+ wined3d_device_set_rendertarget_view(This->wined3d_device, 0, NULL, FALSE);
/* Release the wined3d device. This won't destroy it. */
if (!wined3d_device_decref(This->wined3d_device))
@@ -1818,8 +1818,8 @@ static HRESULT d3d_device_set_render_target(struct d3d_device *device,
return DDERR_INVALIDPARAMS;
}
- if (FAILED(hr = wined3d_device_set_render_target(device->wined3d_device,
- 0, target->wined3d_surface, FALSE)))
+ if (FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device,
+ 0, ddraw_surface_get_rendertarget_view(target), FALSE)))
return hr;
IUnknown_AddRef(rt_iface);
@@ -6818,8 +6818,8 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
wined3d_device_incref(ddraw->wined3d_device);
/* Render to the back buffer */
- hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
- if (FAILED(hr))
+ if (FAILED(hr = wined3d_device_set_rendertarget_view(ddraw->wined3d_device,
+ 0, ddraw_surface_get_rendertarget_view(target), TRUE)))
{
ERR("Failed to set render target, hr %#x.\n", hr);
ddraw_handle_table_destroy(&device->handle_table);
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index 63be3ae..0214a7f 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -322,6 +322,8 @@ static void ddraw_surface_add_iface(struct ddraw_surface *surface)
if (surface->ifaceToRelease)
IUnknown_AddRef(surface->ifaceToRelease);
wined3d_mutex_lock();
+ if (surface->wined3d_rtv)
+ wined3d_rendertarget_view_incref(surface->wined3d_rtv);
if (surface->wined3d_surface)
wined3d_surface_incref(surface->wined3d_surface);
if (surface->wined3d_texture)
@@ -526,6 +528,8 @@ static void ddraw_surface_cleanup(struct ddraw_surface *surface)
surface, surface->ref7, surface->ref4, surface->ref3, surface->ref2, surface->ref1);
}
+ if (surface->wined3d_rtv)
+ wined3d_rendertarget_view_decref(surface->wined3d_rtv);
if (surface->wined3d_texture)
wined3d_texture_decref(surface->wined3d_texture);
if (surface->wined3d_surface)
@@ -1208,11 +1212,12 @@ static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDra
{
struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src);
+ struct wined3d_rendertarget_view *tmp_rtv, *src_rtv, *rtv;
struct ddraw_texture *ddraw_texture, *prev_ddraw_texture;
DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, 0};
- struct wined3d_surface *tmp, *rt;
struct wined3d_texture *texture;
IDirectDrawSurface7 *current;
+ struct wined3d_surface *tmp;
HRESULT hr;
TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
@@ -1225,9 +1230,10 @@ static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDra
wined3d_mutex_lock();
+ tmp_rtv = ddraw_surface_get_rendertarget_view(dst_impl);
tmp = dst_impl->wined3d_surface;
texture = dst_impl->wined3d_texture;
- rt = wined3d_device_get_render_target(dst_impl->ddraw->wined3d_device, 0);
+ rtv = wined3d_device_get_rendertarget_view(dst_impl->ddraw->wined3d_device, 0);
ddraw_texture = wined3d_texture_get_parent(dst_impl->wined3d_texture);
if (src_impl)
@@ -1249,8 +1255,11 @@ static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDra
}
}
- if (rt == dst_impl->wined3d_surface)
- wined3d_device_set_render_target(dst_impl->ddraw->wined3d_device, 0, src_impl->wined3d_surface, FALSE);
+ src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
+ if (rtv == dst_impl->wined3d_rtv)
+ wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE);
+ wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
+ dst_impl->wined3d_rtv = src_rtv;
wined3d_resource_set_parent(wined3d_surface_get_resource(src_impl->wined3d_surface), dst_impl);
dst_impl->wined3d_surface = src_impl->wined3d_surface;
prev_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
@@ -1276,8 +1285,11 @@ static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDra
}
src_impl = impl_from_IDirectDrawSurface7(current);
- if (rt == dst_impl->wined3d_surface)
- wined3d_device_set_render_target(dst_impl->ddraw->wined3d_device, 0, src_impl->wined3d_surface, FALSE);
+ src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
+ if (rtv == dst_impl->wined3d_rtv)
+ wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE);
+ wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
+ dst_impl->wined3d_rtv = src_rtv;
wined3d_resource_set_parent(wined3d_surface_get_resource(src_impl->wined3d_surface), dst_impl);
dst_impl->wined3d_surface = src_impl->wined3d_surface;
prev_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
@@ -1290,8 +1302,10 @@ static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDra
/* We don't have to worry about potential texture bindings, since
* flippable surfaces can never be textures. */
- if (rt == src_impl->wined3d_surface)
- wined3d_device_set_render_target(dst_impl->ddraw->wined3d_device, 0, tmp, FALSE);
+ if (rtv == src_impl->wined3d_rtv)
+ wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, tmp_rtv, FALSE);
+ wined3d_rendertarget_view_set_parent(tmp_rtv, src_impl);
+ src_impl->wined3d_rtv = tmp_rtv;
wined3d_resource_set_parent(wined3d_surface_get_resource(tmp), src_impl);
src_impl->wined3d_surface = tmp;
wined3d_resource_set_parent(wined3d_texture_get_resource(texture), ddraw_texture);
@@ -6227,3 +6241,41 @@ HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, s
return DD_OK;
}
+
+static void STDMETHODCALLTYPE view_wined3d_object_destroyed(void *parent)
+{
+ struct ddraw_surface *surface = parent;
+
+ /* If the surface reference count drops to zero, we release our reference
+ * to the view, but don't clear the pointer yet, in case e.g. a
+ * GetRenderTarget() call brings the surface back before the view is
+ * actually destroyed. When the view is destroyed, we need to clear the
+ * pointer, or a subsequent surface AddRef() would reference it again.
+ *
+ * This is safe because as long as the view still has a reference to the
+ * texture, the surface is also still alive, and we're called before the
+ * view releases that reference. */
+ surface->wined3d_rtv = NULL;
+}
+
+static const struct wined3d_parent_ops ddraw_view_wined3d_parent_ops =
+{
+ view_wined3d_object_destroyed,
+};
+
+struct wined3d_rendertarget_view *ddraw_surface_get_rendertarget_view(struct ddraw_surface *surface)
+{
+ HRESULT hr;
+
+ if (surface->wined3d_rtv)
+ return surface->wined3d_rtv;
+
+ if (FAILED(hr = wined3d_rendertarget_view_create_from_surface(surface->wined3d_surface,
+ surface, &ddraw_view_wined3d_parent_ops, &surface->wined3d_rtv)))
+ {
+ ERR("Failed to create rendertarget view, hr %#x.\n", hr);
+ return NULL;
+ }
+
+ return surface->wined3d_rtv;
+}
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 3d3816f..4a61cc8 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -706,7 +706,7 @@ static void shader_arb_load_constants_internal(struct shader_arb_priv *priv,
{
const struct wined3d_shader *pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL];
const struct arb_ps_compiled_shader *gl_shader = priv->compiled_fprog;
- UINT rt_height = state->fb->render_targets[0]->resource.height;
+ UINT rt_height = state->fb->render_targets[0]->height;
/* Load DirectX 9 float constants for pixel shader */
priv->highest_dirty_ps_const = shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB,
@@ -4673,7 +4673,7 @@ static void shader_arb_select(void *shader_priv, struct wined3d_context *context
}
else
{
- UINT rt_height = state->fb->render_targets[0]->resource.height;
+ UINT rt_height = state->fb->render_targets[0]->height;
shader_arb_ps_local_constants(compiled, context, state, rt_height);
}
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index f62b962..b3573ae 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -2281,7 +2281,7 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine
}
static BOOL context_validate_rt_config(UINT rt_count,
- struct wined3d_surface * const *rts, const struct wined3d_surface *ds)
+ struct wined3d_rendertarget_view * const *rts, const struct wined3d_surface *ds)
{
unsigned int i;
@@ -2289,7 +2289,7 @@ static BOOL context_validate_rt_config(UINT rt_count,
for (i = 0; i < rt_count; ++i)
{
- if (rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL)
+ if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL)
return TRUE;
}
@@ -2301,10 +2301,10 @@ static BOOL context_validate_rt_config(UINT rt_count,
BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_device *device,
UINT rt_count, const struct wined3d_fb_state *fb)
{
+ struct wined3d_rendertarget_view **rts = fb->render_targets;
const struct wined3d_gl_info *gl_info = context->gl_info;
DWORD rt_mask = 0, *cur_mask;
UINT i;
- struct wined3d_surface **rts = fb->render_targets;
if (isStateDirty(context, STATE_FRAMEBUFFER) || fb != &device->fb
|| rt_count != context->gl_info->limits.buffers)
@@ -2316,12 +2316,12 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
{
context_validate_onscreen_formats(context, fb->depth_stencil);
- if (!rt_count || wined3d_resource_is_offscreen(&rts[0]->resource))
+ if (!rt_count || wined3d_resource_is_offscreen(rts[0]->resource))
{
for (i = 0; i < rt_count; ++i)
{
- context->blit_targets[i] = rts[i];
- if (rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL)
+ context->blit_targets[i] = wined3d_rendertarget_view_get_surface(rts[i]);
+ if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL)
rt_mask |= (1 << i);
}
while (i < context->gl_info->limits.buffers)
@@ -2330,12 +2330,12 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
++i;
}
context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, fb->depth_stencil,
- rt_count ? rts[0]->container->resource.draw_binding : WINED3D_LOCATION_TEXTURE_RGB);
+ rt_count ? rts[0]->resource->draw_binding : WINED3D_LOCATION_TEXTURE_RGB);
}
else
{
context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL, WINED3D_LOCATION_DRAWABLE);
- rt_mask = context_generate_rt_mask_from_surface(rts[0]);
+ rt_mask = context_generate_rt_mask_from_surface(wined3d_rendertarget_view_get_surface(rts[0]));
}
/* If the framebuffer is not the device's fb the device's fb has to be reapplied
@@ -2345,20 +2345,23 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
}
else
{
- rt_mask = context_generate_rt_mask_no_fbo(device, rt_count ? rts[0] : NULL);
+ rt_mask = context_generate_rt_mask_no_fbo(device,
+ rt_count ? wined3d_rendertarget_view_get_surface(rts[0]) : NULL);
}
}
else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO
- && (!rt_count || wined3d_resource_is_offscreen(&rts[0]->resource)))
+ && (!rt_count || wined3d_resource_is_offscreen(rts[0]->resource)))
{
for (i = 0; i < rt_count; ++i)
{
- if (rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL) rt_mask |= (1 << i);
+ if (rts[i] && rts[i]->format->id != WINED3DFMT_NULL)
+ rt_mask |= (1 << i);
}
}
else
{
- rt_mask = context_generate_rt_mask_no_fbo(device, rt_count ? rts[0] : NULL);
+ rt_mask = context_generate_rt_mask_no_fbo(device,
+ rt_count ? wined3d_rendertarget_view_get_surface(rts[0]) : NULL);
}
cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask;
@@ -2395,13 +2398,15 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const struct wined3d_device *device)
{
const struct wined3d_state *state = &device->state;
- struct wined3d_surface **rts = state->fb->render_targets;
+ struct wined3d_rendertarget_view **rts = state->fb->render_targets;
struct wined3d_shader *ps = state->shader[WINED3D_SHADER_TYPE_PIXEL];
DWORD rt_mask, rt_mask_bits;
unsigned int i;
- if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return context_generate_rt_mask_no_fbo(device, rts[0]);
- else if (!context->render_offscreen) return context_generate_rt_mask_from_surface(rts[0]);
+ if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
+ return context_generate_rt_mask_no_fbo(device, wined3d_rendertarget_view_get_surface(rts[0]));
+ else if (!context->render_offscreen)
+ return context_generate_rt_mask_from_surface(wined3d_rendertarget_view_get_surface(rts[0]));
rt_mask = ps ? ps->reg_maps.rt_mask : 1;
rt_mask &= context->d3d_info->valid_rt_mask;
@@ -2410,7 +2415,7 @@ static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const
while (rt_mask_bits)
{
rt_mask_bits &= ~(1 << i);
- if (!rts[i] || rts[i]->resource.format->id == WINED3DFMT_NULL)
+ if (!rts[i] || rts[i]->format->id == WINED3DFMT_NULL)
rt_mask &= ~(1 << i);
i++;
@@ -2435,8 +2440,14 @@ void context_state_fb(struct wined3d_context *context, const struct wined3d_stat
}
else
{
- context_apply_fbo_state(context, GL_FRAMEBUFFER, fb->render_targets, fb->depth_stencil,
- fb->render_targets[0]->container->resource.draw_binding);
+ unsigned int i;
+
+ for (i = 0; i < context->gl_info->limits.buffers; ++i)
+ {
+ context->blit_targets[i] = wined3d_rendertarget_view_get_surface(fb->render_targets[i]);
+ }
+ context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, fb->depth_stencil,
+ fb->render_targets[0]->resource->draw_binding);
}
}
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 684ac9f..df1c4e3 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -31,7 +31,7 @@ enum wined3d_cs_op
WINED3D_CS_OP_DRAW,
WINED3D_CS_OP_SET_VIEWPORT,
WINED3D_CS_OP_SET_SCISSOR_RECT,
- WINED3D_CS_OP_SET_RENDER_TARGET,
+ WINED3D_CS_OP_SET_RENDERTARGET_VIEW,
WINED3D_CS_OP_SET_DEPTH_STENCIL,
WINED3D_CS_OP_SET_VERTEX_DECLARATION,
WINED3D_CS_OP_SET_STREAM_SOURCE,
@@ -95,11 +95,11 @@ struct wined3d_cs_set_scissor_rect
const RECT *rect;
};
-struct wined3d_cs_set_render_target
+struct wined3d_cs_set_rendertarget_view
{
enum wined3d_cs_op opcode;
- UINT render_target_idx;
- struct wined3d_surface *render_target;
+ unsigned int view_idx;
+ struct wined3d_rendertarget_view *view;
};
struct wined3d_cs_set_depth_stencil
@@ -346,23 +346,23 @@ void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect)
cs->ops->submit(cs);
}
-static void wined3d_cs_exec_set_render_target(struct wined3d_cs *cs, const void *data)
+static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs *cs, const void *data)
{
- const struct wined3d_cs_set_render_target *op = data;
+ const struct wined3d_cs_set_rendertarget_view *op = data;
- cs->state.fb->render_targets[op->render_target_idx] = op->render_target;
+ cs->state.fb->render_targets[op->view_idx] = op->view;
device_invalidate_state(cs->device, STATE_FRAMEBUFFER);
}
-void wined3d_cs_emit_set_render_target(struct wined3d_cs *cs, UINT render_target_idx,
- struct wined3d_surface *render_target)
+void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int view_idx,
+ struct wined3d_rendertarget_view *view)
{
- struct wined3d_cs_set_render_target *op;
+ struct wined3d_cs_set_rendertarget_view *op;
op = cs->ops->require_space(cs, sizeof(*op));
- op->opcode = WINED3D_CS_OP_SET_RENDER_TARGET;
- op->render_target_idx = render_target_idx;
- op->render_target = render_target;
+ op->opcode = WINED3D_CS_OP_SET_RENDERTARGET_VIEW;
+ op->view_idx = view_idx;
+ op->view = view;
cs->ops->submit(cs);
}
@@ -851,7 +851,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
/* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw,
/* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport,
/* WINED3D_CS_OP_SET_SCISSOR_RECT */ wined3d_cs_exec_set_scissor_rect,
- /* WINED3D_CS_OP_SET_RENDER_TARGET */ wined3d_cs_exec_set_render_target,
+ /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view,
/* WINED3D_CS_OP_SET_DEPTH_STENCIL */ wined3d_cs_exec_set_depth_stencil,
/* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration,
/* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source,
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 962c9c8..cd5f5f4 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -286,8 +286,8 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
UINT rect_count, const RECT *rects, const RECT *draw_rect, DWORD flags, const struct wined3d_color *color,
float depth, DWORD stencil)
{
+ struct wined3d_surface *target = rt_count ? wined3d_rendertarget_view_get_surface(fb->render_targets[0]) : NULL;
const RECT *clear_rect = (rect_count > 0 && rects) ? (const RECT *)rects : NULL;
- struct wined3d_surface *target = rt_count ? fb->render_targets[0] : NULL;
const struct wined3d_gl_info *gl_info;
UINT drawable_width, drawable_height;
struct wined3d_context *context;
@@ -308,7 +308,7 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
{
for (i = 0; i < rt_count; ++i)
{
- struct wined3d_surface *rt = fb->render_targets[i];
+ struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(fb->render_targets[i]);
if (rt)
surface_load_location(rt, rt->container->resource.draw_binding);
}
@@ -386,7 +386,7 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c
{
for (i = 0; i < rt_count; ++i)
{
- struct wined3d_surface *rt = fb->render_targets[i];
+ struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(fb->render_targets[i]);
if (rt)
{
@@ -851,11 +851,10 @@ static void device_init_swapchain_state(struct wined3d_device *device, struct wi
{
for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
{
- wined3d_device_set_render_target(device, i, NULL, FALSE);
+ wined3d_device_set_rendertarget_view(device, i, NULL, FALSE);
}
- if (swapchain->back_buffers && swapchain->back_buffers[0])
- wined3d_device_set_render_target(device, 0,
- surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0)), TRUE);
+ if (device->back_buffer_view)
+ wined3d_device_set_rendertarget_view(device, 0, device->back_buffer_view, TRUE);
}
wined3d_device_set_depth_stencil(device, ds_enable ? device->auto_depth_stencil : NULL);
@@ -904,6 +903,14 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
goto err_out;
}
+ if (swapchain_desc->backbuffer_count && FAILED(hr = wined3d_rendertarget_view_create_from_surface(
+ surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0)),
+ NULL, &wined3d_null_parent_ops, &device->back_buffer_view)))
+ {
+ ERR("Failed to create rendertarget view, hr %#x.\n", hr);
+ goto err_out;
+ }
+
device->swapchain_count = 1;
device->swapchains = HeapAlloc(GetProcessHeap(), 0, device->swapchain_count * sizeof(*device->swapchains));
if (!device->swapchains)
@@ -964,6 +971,8 @@ err_out:
HeapFree(GetProcessHeap(), 0, device->fb.render_targets);
HeapFree(GetProcessHeap(), 0, device->swapchains);
device->swapchain_count = 0;
+ if (device->back_buffer_view)
+ wined3d_rendertarget_view_decref(device->back_buffer_view);
if (swapchain)
wined3d_swapchain_decref(swapchain);
if (device->blit_priv)
@@ -1083,7 +1092,12 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
for (i = 0; i < gl_info->limits.buffers; ++i)
{
- wined3d_device_set_render_target(device, i, NULL, FALSE);
+ wined3d_device_set_rendertarget_view(device, i, NULL, FALSE);
+ }
+ if (device->back_buffer_view)
+ {
+ wined3d_rendertarget_view_decref(device->back_buffer_view);
+ device->back_buffer_view = NULL;
}
context_release(context);
@@ -3213,8 +3227,8 @@ HRESULT CDECL wined3d_device_clear(struct wined3d_device *device, DWORD rect_cou
}
else if (flags & WINED3DCLEAR_TARGET)
{
- if (ds->resource.width < device->fb.render_targets[0]->resource.width
- || ds->resource.height < device->fb.render_targets[0]->resource.height)
+ if (ds->resource.width < device->fb.render_targets[0]->width
+ || ds->resource.height < device->fb.render_targets[0]->height)
{
WARN("Silently ignoring depth and target clear with mismatching sizes\n");
return WINED3D_OK;
@@ -3532,11 +3546,10 @@ HRESULT CDECL wined3d_device_validate_device(const struct wined3d_device *device
if (state->render_states[WINED3D_RS_ZENABLE] || state->render_states[WINED3D_RS_ZWRITEENABLE]
|| state->render_states[WINED3D_RS_STENCILENABLE])
{
+ struct wined3d_rendertarget_view *rt = device->fb.render_targets[0];
struct wined3d_surface *ds = device->fb.depth_stencil;
- struct wined3d_surface *target = device->fb.render_targets[0];
- if(ds && target
- && (ds->resource.width < target->resource.width || ds->resource.height < target->resource.height))
+ if(ds && rt && (ds->resource.width < rt->width || ds->resource.height < rt->height))
{
WARN("Depth stencil is smaller than the color buffer, returning D3DERR_CONFLICTINGRENDERSTATE\n");
return WINED3DERR_CONFLICTINGRENDERSTATE;
@@ -3769,18 +3782,18 @@ void CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *device,
ERR("Color fill failed, hr %#x.\n", hr);
}
-struct wined3d_surface * CDECL wined3d_device_get_render_target(const struct wined3d_device *device,
- UINT render_target_idx)
+struct wined3d_rendertarget_view * CDECL wined3d_device_get_rendertarget_view(const struct wined3d_device *device,
+ unsigned int view_idx)
{
- TRACE("device %p, render_target_idx %u.\n", device, render_target_idx);
+ TRACE("device %p, view_idx %u.\n", device, view_idx);
- if (render_target_idx >= device->adapter->gl_info.limits.buffers)
+ if (view_idx >= device->adapter->gl_info.limits.buffers)
{
WARN("Only %u render targets are supported.\n", device->adapter->gl_info.limits.buffers);
return NULL;
}
- return device->fb.render_targets[render_target_idx];
+ return device->fb.render_targets[view_idx];
}
struct wined3d_surface * CDECL wined3d_device_get_depth_stencil(const struct wined3d_device *device)
@@ -3790,61 +3803,61 @@ struct wined3d_surface * CDECL wined3d_device_get_depth_stencil(const struct win
return device->fb.depth_stencil;
}
-HRESULT CDECL wined3d_device_set_render_target(struct wined3d_device *device,
- UINT render_target_idx, struct wined3d_surface *render_target, BOOL set_viewport)
+HRESULT CDECL wined3d_device_set_rendertarget_view(struct wined3d_device *device,
+ unsigned int view_idx, struct wined3d_rendertarget_view *view, BOOL set_viewport)
{
- struct wined3d_surface *prev;
+ struct wined3d_rendertarget_view *prev;
- TRACE("device %p, render_target_idx %u, render_target %p, set_viewport %#x.\n",
- device, render_target_idx, render_target, set_viewport);
+ TRACE("device %p, view_idx %u, view %p, set_viewport %#x.\n",
+ device, view_idx, view, set_viewport);
- if (render_target_idx >= device->adapter->gl_info.limits.buffers)
+ if (view_idx >= device->adapter->gl_info.limits.buffers)
{
WARN("Only %u render targets are supported.\n", device->adapter->gl_info.limits.buffers);
return WINED3DERR_INVALIDCALL;
}
- if (render_target && !(render_target->resource.usage & WINED3DUSAGE_RENDERTARGET))
+ if (view && !(view->resource->usage & WINED3DUSAGE_RENDERTARGET))
{
- WARN("Surface %p doesn't have render target usage.\n", render_target);
+ WARN("View resource %p doesn't have render target usage.\n", view->resource);
return WINED3DERR_INVALIDCALL;
}
/* Set the viewport and scissor rectangles, if requested. Tests show that
* stateblock recording is ignored, the change goes directly into the
* primary stateblock. */
- if (!render_target_idx && set_viewport)
+ if (!view_idx && set_viewport)
{
struct wined3d_state *state = &device->state;
state->viewport.x = 0;
state->viewport.y = 0;
- state->viewport.width = render_target->resource.width;
- state->viewport.height = render_target->resource.height;
+ state->viewport.width = view->width;
+ state->viewport.height = view->height;
state->viewport.min_z = 0.0f;
state->viewport.max_z = 1.0f;
wined3d_cs_emit_set_viewport(device->cs, &state->viewport);
state->scissor_rect.top = 0;
state->scissor_rect.left = 0;
- state->scissor_rect.right = render_target->resource.width;
- state->scissor_rect.bottom = render_target->resource.height;
+ state->scissor_rect.right = view->width;
+ state->scissor_rect.bottom = view->height;
wined3d_cs_emit_set_scissor_rect(device->cs, &state->scissor_rect);
}
- prev = device->fb.render_targets[render_target_idx];
- if (render_target == prev)
+ prev = device->fb.render_targets[view_idx];
+ if (view == prev)
return WINED3D_OK;
- if (render_target)
- wined3d_surface_incref(render_target);
- device->fb.render_targets[render_target_idx] = render_target;
- wined3d_cs_emit_set_render_target(device->cs, render_target_idx, render_target);
+ if (view)
+ wined3d_rendertarget_view_incref(view);
+ device->fb.render_targets[view_idx] = view;
+ wined3d_cs_emit_set_rendertarget_view(device->cs, view_idx, view);
/* Release after the assignment, to prevent device_resource_released()
* from seeing the surface as still in use. */
if (prev)
- wined3d_surface_decref(prev);
+ wined3d_rendertarget_view_decref(prev);
return WINED3D_OK;
}
@@ -4242,11 +4255,8 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
{
for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
{
- wined3d_device_set_render_target(device, i, NULL, FALSE);
+ wined3d_device_set_rendertarget_view(device, i, NULL, FALSE);
}
- if (swapchain->back_buffers && swapchain->back_buffers[0])
- wined3d_device_set_render_target(device, 0,
- surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0)), FALSE);
}
wined3d_device_set_depth_stencil(device, NULL);
@@ -4439,6 +4449,19 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
}
}
+ if (device->back_buffer_view)
+ {
+ wined3d_rendertarget_view_decref(device->back_buffer_view);
+ device->back_buffer_view = NULL;
+ }
+ if (swapchain->desc.backbuffer_count && FAILED(hr = wined3d_rendertarget_view_create_from_surface(
+ surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0)),
+ NULL, &wined3d_null_parent_ops, &device->back_buffer_view)))
+ {
+ ERR("Failed to create rendertarget view, hr %#x.\n", hr);
+ return hr;
+ }
+
if (!swapchain_desc->windowed != !swapchain->desc.windowed
|| DisplayModeChanged)
{
@@ -4521,22 +4544,24 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
device_init_swapchain_state(device, swapchain);
}
- else
+ else if (device->back_buffer_view)
{
- struct wined3d_surface *rt = device->fb.render_targets[0];
+ struct wined3d_rendertarget_view *view = device->back_buffer_view;
struct wined3d_state *state = &device->state;
+ wined3d_device_set_rendertarget_view(device, 0, view, FALSE);
+
/* Note the min_z / max_z is not reset. */
state->viewport.x = 0;
state->viewport.y = 0;
- state->viewport.width = rt->resource.width;
- state->viewport.height = rt->resource.height;
+ state->viewport.width = view->width;
+ state->viewport.height = view->height;
wined3d_cs_emit_set_viewport(device->cs, &state->viewport);
state->scissor_rect.top = 0;
state->scissor_rect.left = 0;
- state->scissor_rect.right = rt->resource.width;
- state->scissor_rect.bottom = rt->resource.height;
+ state->scissor_rect.right = view->width;
+ state->scissor_rect.bottom = view->height;
wined3d_cs_emit_set_scissor_rect(device->cs, &state->scissor_rect);
}
@@ -4627,7 +4652,7 @@ void device_resource_released(struct wined3d_device *device, struct wined3d_reso
for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
{
- if (device->fb.render_targets[i] == surface)
+ if (wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]) == surface)
{
ERR("Surface %p is still in use as render target %u.\n", surface, i);
device->fb.render_targets[i] = NULL;
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 621e3f2..aa9f661 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -613,7 +613,7 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co
/* Invalidate the back buffer memory so LockRect will read it the next time */
for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
{
- struct wined3d_surface *target = device->fb.render_targets[i];
+ struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]);
if (target)
{
surface_load_location(target, target->container->resource.draw_binding);
@@ -622,7 +622,7 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co
}
}
- context = context_acquire(device, device->fb.render_targets[0]);
+ context = context_acquire(device, wined3d_rendertarget_view_get_surface(device->fb.render_targets[0]));
if (!context->valid)
{
context_release(context);
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 1097d87..bebcfd4 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -1257,7 +1257,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
{
float ycorrection[] =
{
- context->render_offscreen ? 0.0f : fb->render_targets[0]->resource.height,
+ context->render_offscreen ? 0.0f : fb->render_targets[0]->height,
context->render_offscreen ? 1.0f : -1.0f,
0.0f,
0.0f,
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index 06ed09a..1076628 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -2036,8 +2036,8 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3
memset(args, 0, sizeof(*args)); /* FIXME: Make sure all bits are set. */
if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] && state->render_states[WINED3D_RS_SRGBWRITEENABLE])
{
- const struct wined3d_surface *rt = state->fb->render_targets[0];
- if (rt->resource.format->flags & WINED3DFMT_FLAG_SRGB_WRITE)
+ const struct wined3d_format *rt_format = state->fb->render_targets[0]->format;
+ if (rt_format->flags & WINED3DFMT_FLAG_SRGB_WRITE)
{
static unsigned int warned = 0;
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index fc9c38d..6f0f96f 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -381,7 +381,7 @@ static GLenum gl_blend_factor(enum wined3d_blend factor, const struct wined3d_fo
static void state_blend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
- const struct wined3d_surface *target = state->fb->render_targets[0];
+ const struct wined3d_format *rt_format = state->fb->render_targets[0]->format;
const struct wined3d_gl_info *gl_info = context->gl_info;
GLenum srcBlend, dstBlend;
enum wined3d_blend d3d_blend;
@@ -395,8 +395,7 @@ static void state_blend(struct wined3d_context *context, const struct wined3d_st
/* Disable blending in all cases even without pixelshaders.
* With blending on we could face a big performance penalty.
* The d3d9 visual test confirms the behavior. */
- if (context->render_offscreen
- && !(target->resource.format->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
+ if (context->render_offscreen && !(rt_format->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
{
gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
checkGLcall("glDisable GL_BLEND");
@@ -432,9 +431,8 @@ static void state_blend(struct wined3d_context *context, const struct wined3d_st
}
else
{
- srcBlend = gl_blend_factor(d3d_blend, target->resource.format);
- dstBlend = gl_blend_factor(state->render_states[WINED3D_RS_DESTBLEND],
- target->resource.format);
+ srcBlend = gl_blend_factor(d3d_blend, rt_format);
+ dstBlend = gl_blend_factor(state->render_states[WINED3D_RS_DESTBLEND], rt_format);
}
if (state->render_states[WINED3D_RS_EDGEANTIALIAS]
@@ -484,9 +482,8 @@ static void state_blend(struct wined3d_context *context, const struct wined3d_st
}
else
{
- srcBlendAlpha = gl_blend_factor(d3d_blend, target->resource.format);
- dstBlendAlpha = gl_blend_factor(state->render_states[WINED3D_RS_DESTBLENDALPHA],
- target->resource.format);
+ srcBlendAlpha = gl_blend_factor(d3d_blend, rt_format);
+ dstBlendAlpha = gl_blend_factor(state->render_states[WINED3D_RS_DESTBLENDALPHA], rt_format);
}
GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha));
@@ -4637,14 +4634,14 @@ void vertexdeclaration(struct wined3d_context *context, const struct wined3d_sta
static void viewport_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
- const struct wined3d_surface *target = state->fb->render_targets[0];
+ const struct wined3d_rendertarget_view *target = state->fb->render_targets[0];
const struct wined3d_gl_info *gl_info = context->gl_info;
struct wined3d_viewport vp = state->viewport;
- if (vp.width > target->resource.width)
- vp.width = target->resource.width;
- if (vp.height > target->resource.height)
- vp.height = target->resource.height;
+ if (vp.width > target->width)
+ vp.width = target->width;
+ if (vp.height > target->height)
+ vp.height = target->height;
gl_info->gl_ops.gl.p_glDepthRange(vp.min_z, vp.max_z);
checkGLcall("glDepthRange");
@@ -4658,7 +4655,7 @@ static void viewport_miscpart(struct wined3d_context *context, const struct wine
{
UINT width, height;
- surface_get_drawable_size(target, context, &width, &height);
+ surface_get_drawable_size(wined3d_rendertarget_view_get_surface(target), context, &width, &height);
gl_info->gl_ops.gl.p_glViewport(vp.x, (height - (vp.y + vp.height)),
vp.width, vp.height);
}
@@ -4817,11 +4814,11 @@ static void scissorrect(struct wined3d_context *context, const struct wined3d_st
}
else
{
- const struct wined3d_surface *target = state->fb->render_targets[0];
+ const struct wined3d_rendertarget_view *target = state->fb->render_targets[0];
UINT height;
UINT width;
- surface_get_drawable_size(target, context, &width, &height);
+ surface_get_drawable_size(wined3d_rendertarget_view_get_surface(target), context, &width, &height);
gl_info->gl_ops.gl.p_glScissor(r->left, height - r->bottom, r->right - r->left, r->bottom - r->top);
}
checkGLcall("glScissor");
@@ -4884,13 +4881,13 @@ static void psorigin(struct wined3d_context *context, const struct wined3d_state
void state_srgbwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
+ const struct wined3d_format *rt_format = state->fb->render_targets[0]->format;
const struct wined3d_gl_info *gl_info = context->gl_info;
- const struct wined3d_surface *rt = state->fb->render_targets[0];
TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
if (state->render_states[WINED3D_RS_SRGBWRITEENABLE]
- && rt->resource.format->flags & WINED3DFMT_FLAG_SRGB_WRITE)
+ && rt_format->flags & WINED3DFMT_FLAG_SRGB_WRITE)
gl_info->gl_ops.gl.p_glEnable(GL_FRAMEBUFFER_SRGB);
else
gl_info->gl_ops.gl.p_glDisable(GL_FRAMEBUFFER_SRGB);
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 65517ec..b466524 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -3977,6 +3977,7 @@ static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RE
enum wined3d_texture_filter_type filter)
{
struct wined3d_device *device = dst_surface->resource.device;
+ const struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(device->fb.render_targets[0]);
const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
struct wined3d_swapchain *src_swapchain, *dst_swapchain;
@@ -4009,9 +4010,7 @@ static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RE
}
/* Early sort out of cases where no render target is used */
- if (!dst_swapchain && !src_swapchain
- && src_surface != device->fb.render_targets[0]
- && dst_surface != device->fb.render_targets[0])
+ if (!dst_swapchain && !src_swapchain && src_surface != rt && dst_surface != rt)
{
TRACE("No surface is render target, not using hardware blit.\n");
return WINED3DERR_INVALIDCALL;
@@ -4040,16 +4039,16 @@ static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RE
if (dst_swapchain)
{
/* Handled with regular texture -> swapchain blit */
- if (src_surface == device->fb.render_targets[0])
+ if (src_surface == rt)
TRACE("Blit from active render target to a swapchain\n");
}
- else if (src_swapchain && dst_surface == device->fb.render_targets[0])
+ else if (src_swapchain && dst_surface == rt)
{
FIXME("Implement blit from a swapchain to the active render target\n");
return WINED3DERR_INVALIDCALL;
}
- if ((src_swapchain || src_surface == device->fb.render_targets[0]) && !dst_swapchain)
+ if ((src_swapchain || src_surface == rt) && !dst_swapchain)
{
/* Blit from render target to texture */
BOOL stretchx;
@@ -4899,9 +4898,19 @@ static HRESULT ffp_blit_color_fill(struct wined3d_device *device, struct wined3d
const RECT *dst_rect, const struct wined3d_color *color)
{
const RECT draw_rect = {0, 0, dst_surface->resource.width, dst_surface->resource.height};
- struct wined3d_fb_state fb = {&dst_surface, NULL};
+ struct wined3d_rendertarget_view *view;
+ struct wined3d_fb_state fb = {&view, NULL};
+ HRESULT hr;
+
+ if (FAILED(hr = wined3d_rendertarget_view_create_from_surface(dst_surface,
+ NULL, &wined3d_null_parent_ops, &view)))
+ {
+ ERR("Failed to create rendertarget view, hr %#x.\n", hr);
+ return hr;
+ }
device_clear_render_targets(device, 1, &fb, 1, dst_rect, &draw_rect, WINED3DCLEAR_TARGET, color, 0.0f, 0);
+ wined3d_rendertarget_view_decref(view);
return WINED3D_OK;
}
@@ -5901,7 +5910,7 @@ cpu:
}
static HRESULT surface_init(struct wined3d_surface *surface, struct wined3d_texture *container,
- const struct wined3d_resource_desc *desc, GLenum target, GLint level, DWORD flags)
+ const struct wined3d_resource_desc *desc, GLenum target, unsigned int level, unsigned int layer, DWORD flags)
{
struct wined3d_device *device = container->resource.device;
const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
@@ -5983,6 +5992,7 @@ static HRESULT surface_init(struct wined3d_surface *surface, struct wined3d_text
surface->resource.map_binding = WINED3D_LOCATION_SYSMEM;
surface->texture_target = target;
surface->texture_level = level;
+ surface->texture_layer = layer;
/* Call the private setup routine */
if (FAILED(hr = surface->surface_ops->surface_private_setup(surface)))
@@ -6010,7 +6020,7 @@ static HRESULT surface_init(struct wined3d_surface *surface, struct wined3d_text
}
HRESULT wined3d_surface_create(struct wined3d_texture *container, const struct wined3d_resource_desc *desc,
- GLenum target, GLint level, DWORD flags, struct wined3d_surface **surface)
+ GLenum target, unsigned int level, unsigned int layer, DWORD flags, struct wined3d_surface **surface)
{
struct wined3d_device_parent *device_parent = container->resource.device->device_parent;
const struct wined3d_parent_ops *parent_ops;
@@ -6019,15 +6029,15 @@ HRESULT wined3d_surface_create(struct wined3d_texture *container, const struct w
HRESULT hr;
TRACE("container %p, width %u, height %u, format %s, usage %s (%#x), pool %s, "
- "multisample_type %#x, multisample_quality %u, target %#x, level %d, flags %#x, surface %p.\n",
+ "multisample_type %#x, multisample_quality %u, target %#x, level %u, layer %u, flags %#x, surface %p.\n",
container, desc->width, desc->height, debug_d3dformat(desc->format),
debug_d3dusage(desc->usage), desc->usage, debug_d3dpool(desc->pool),
- desc->multisample_type, desc->multisample_quality, target, level, flags, surface);
+ desc->multisample_type, desc->multisample_quality, target, level, layer, flags, surface);
if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
return E_OUTOFMEMORY;
- if (FAILED(hr = surface_init(object, container, desc, target, level, flags)))
+ if (FAILED(hr = surface_init(object, container, desc, target, level, layer, flags)))
{
WARN("Failed to initialize surface, returning %#x.\n", hr);
HeapFree(GetProcessHeap(), 0, object);
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index f595e16..1d9b7fb 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -907,7 +907,7 @@ static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wi
struct wined3d_surface *surface;
if (FAILED(hr = wined3d_surface_create(texture, &surface_desc,
- cube_targets[j], i, surface_flags, &surface)))
+ cube_targets[j], i, j, surface_flags, &surface)))
{
WARN("Failed to create surface, hr %#x.\n", hr);
wined3d_texture_cleanup(texture);
@@ -1061,7 +1061,7 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
struct wined3d_surface *surface;
if (FAILED(hr = wined3d_surface_create(texture, &surface_desc,
- texture->target, i, surface_flags, &surface)))
+ texture->target, i, 0, surface_flags, &surface)))
{
WARN("Failed to create surface, hr %#x.\n", hr);
wined3d_texture_cleanup(texture);
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 286638a..68eb735 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -3213,7 +3213,7 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d
unsigned int i;
DWORD ttff;
DWORD cop, aop, carg0, carg1, carg2, aarg0, aarg1, aarg2;
- const struct wined3d_surface *rt = state->fb->render_targets[0];
+ const struct wined3d_format *rt_format = state->fb->render_targets[0]->format;
const struct wined3d_gl_info *gl_info = context->gl_info;
const struct wined3d_d3d_info *d3d_info = context->d3d_info;
@@ -3427,7 +3427,7 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d
}
if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB]
&& state->render_states[WINED3D_RS_SRGBWRITEENABLE]
- && rt->resource.format->flags & WINED3DFMT_FLAG_SRGB_WRITE)
+ && rt_format->flags & WINED3DFMT_FLAG_SRGB_WRITE)
{
settings->sRGB_write = 1;
} else {
diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c
index 7d9e742..5ceebdb 100644
--- a/dlls/wined3d/view.c
+++ b/dlls/wined3d/view.c
@@ -41,6 +41,9 @@ ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *v
if (!refcount)
{
+ /* Call wined3d_object_destroyed() before releasing the resource,
+ * since releasing the resource may end up destroying the parent. */
+ view->parent_ops->wined3d_object_destroyed(view->parent);
wined3d_resource_decref(view->resource);
HeapFree(GetProcessHeap(), 0, view);
}
@@ -55,6 +58,29 @@ void * CDECL wined3d_rendertarget_view_get_parent(const struct wined3d_rendertar
return view->parent;
}
+void * CDECL wined3d_rendertarget_view_get_sub_resource_parent(const struct wined3d_rendertarget_view *view)
+{
+ struct wined3d_resource *sub_resource;
+
+ TRACE("view %p.\n", view);
+
+ if (view->resource->type == WINED3D_RTYPE_BUFFER)
+ return wined3d_buffer_get_parent(buffer_from_resource(view->resource));
+
+ if (!(sub_resource = wined3d_texture_get_sub_resource(wined3d_texture_from_resource(view->resource),
+ view->sub_resource_idx)))
+ return NULL;
+
+ return wined3d_resource_get_parent(sub_resource);
+}
+
+void CDECL wined3d_rendertarget_view_set_parent(struct wined3d_rendertarget_view *view, void *parent)
+{
+ TRACE("view %p, parent %p.\n", view, parent);
+
+ view->parent = parent;
+}
+
struct wined3d_resource * CDECL wined3d_rendertarget_view_get_resource(const struct wined3d_rendertarget_view *view)
{
TRACE("view %p.\n", view);
@@ -63,7 +89,8 @@ struct wined3d_resource * CDECL wined3d_rendertarget_view_get_resource(const str
}
static void wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *view,
- const struct wined3d_rendertarget_view_desc *desc, struct wined3d_resource *resource, void *parent)
+ const struct wined3d_rendertarget_view_desc *desc, struct wined3d_resource *resource,
+ void *parent, const struct wined3d_parent_ops *parent_ops)
{
const struct wined3d_gl_info *gl_info = &resource->device->adapter->gl_info;
@@ -71,6 +98,7 @@ static void wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *vie
view->resource = resource;
wined3d_resource_incref(resource);
view->parent = parent;
+ view->parent_ops = parent_ops;
view->format = wined3d_get_format(gl_info, desc->format_id);
if (resource->type == WINED3D_RTYPE_BUFFER)
@@ -97,7 +125,8 @@ static void wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *vie
}
HRESULT CDECL wined3d_rendertarget_view_create(const struct wined3d_rendertarget_view_desc *desc,
- struct wined3d_resource *resource, void *parent, struct wined3d_rendertarget_view **view)
+ struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
+ struct wined3d_rendertarget_view **view)
{
struct wined3d_rendertarget_view *object;
@@ -107,10 +136,25 @@ HRESULT CDECL wined3d_rendertarget_view_create(const struct wined3d_rendertarget
if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
return E_OUTOFMEMORY;
- wined3d_rendertarget_view_init(object, desc, resource, parent);
+ wined3d_rendertarget_view_init(object, desc, resource, parent, parent_ops);
TRACE("Created render target view %p.\n", object);
*view = object;
return WINED3D_OK;
}
+
+HRESULT CDECL wined3d_rendertarget_view_create_from_surface(struct wined3d_surface *surface,
+ void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_rendertarget_view **view)
+{
+ struct wined3d_rendertarget_view_desc desc;
+
+ TRACE("surface %p, view %p.\n", surface, view);
+
+ desc.format_id = surface->resource.format->id;
+ desc.u.texture.level_idx = surface->texture_level;
+ desc.u.texture.layer_idx = surface->texture_layer;
+ desc.u.texture.layer_count = 1;
+
+ return wined3d_rendertarget_view_create(&desc, &surface->container->resource, parent, parent_ops, view);
+}
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index 722ad18..bde427f 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -75,7 +75,7 @@
@ cdecl wined3d_device_get_ps_sampler(ptr long)
@ cdecl wined3d_device_get_raster_status(ptr long ptr)
@ cdecl wined3d_device_get_render_state(ptr long)
-@ cdecl wined3d_device_get_render_target(ptr long)
+@ cdecl wined3d_device_get_rendertarget_view(ptr long)
@ cdecl wined3d_device_get_sampler_state(ptr long long)
@ cdecl wined3d_device_get_scissor_rect(ptr ptr)
@ cdecl wined3d_device_get_software_vertex_processing(ptr)
@@ -130,7 +130,7 @@
@ cdecl wined3d_device_set_ps_consts_i(ptr long ptr long)
@ cdecl wined3d_device_set_ps_sampler(ptr long ptr)
@ cdecl wined3d_device_set_render_state(ptr long long)
-@ cdecl wined3d_device_set_render_target(ptr long ptr long)
+@ cdecl wined3d_device_set_rendertarget_view(ptr long ptr long)
@ cdecl wined3d_device_set_sampler_state(ptr long long long)
@ cdecl wined3d_device_set_scissor_rect(ptr ptr)
@ cdecl wined3d_device_set_software_vertex_processing(ptr long)
@@ -177,11 +177,14 @@
@ cdecl wined3d_resource_set_parent(ptr ptr)
@ cdecl wined3d_resource_set_priority(ptr long)
-@ cdecl wined3d_rendertarget_view_create(ptr ptr ptr ptr)
+@ cdecl wined3d_rendertarget_view_create(ptr ptr ptr ptr ptr)
+@ cdecl wined3d_rendertarget_view_create_from_surface(ptr ptr ptr ptr)
@ cdecl wined3d_rendertarget_view_decref(ptr)
@ cdecl wined3d_rendertarget_view_get_parent(ptr)
@ cdecl wined3d_rendertarget_view_get_resource(ptr)
+@ cdecl wined3d_rendertarget_view_get_sub_resource_parent(ptr)
@ cdecl wined3d_rendertarget_view_incref(ptr)
+@ cdecl wined3d_rendertarget_view_set_parent(ptr ptr)
@ cdecl wined3d_sampler_create(ptr ptr)
@ cdecl wined3d_sampler_decref(ptr)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 81cbb29..5488178 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1175,7 +1175,7 @@ struct wined3d_context
struct wined3d_fb_state
{
- struct wined3d_surface **render_targets;
+ struct wined3d_rendertarget_view **render_targets;
struct wined3d_surface *depth_stencil;
};
@@ -1945,6 +1945,7 @@ struct wined3d_device
struct wined3d_device_creation_parameters create_parms;
HWND focus_window;
+ struct wined3d_rendertarget_view *back_buffer_view;
struct wined3d_swapchain **swapchains;
UINT swapchain_count;
@@ -2262,8 +2263,9 @@ struct wined3d_surface
GLuint pbo;
GLuint rb_multisample;
GLuint rb_resolved;
- GLint texture_level;
GLenum texture_target;
+ unsigned int texture_level;
+ unsigned int texture_layer;
RECT lockedRect;
int lockCount;
@@ -2323,7 +2325,8 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P
struct wined3d_surface *src_surface, const RECT *src_rect) DECLSPEC_HIDDEN;
void surface_validate_location(struct wined3d_surface *surface, DWORD location) DECLSPEC_HIDDEN;
HRESULT wined3d_surface_create(struct wined3d_texture *container, const struct wined3d_resource_desc *desc,
- GLenum target, GLint level, DWORD flags, struct wined3d_surface **surface) DECLSPEC_HIDDEN;
+ GLenum target, unsigned int level, unsigned int layer, DWORD flags,
+ struct wined3d_surface **surface) DECLSPEC_HIDDEN;
void wined3d_surface_destroy(struct wined3d_surface *surface) DECLSPEC_HIDDEN;
void surface_prepare_map_memory(struct wined3d_surface *surface) DECLSPEC_HIDDEN;
@@ -2509,8 +2512,8 @@ void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buff
void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_material *material) DECLSPEC_HIDDEN;
void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs,
enum wined3d_render_state state, DWORD value) DECLSPEC_HIDDEN;
-void wined3d_cs_emit_set_render_target(struct wined3d_cs *cs, UINT render_target_idx,
- struct wined3d_surface *render_target) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int view_idx,
+ struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN;
void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type type,
UINT sampler_idx, struct wined3d_sampler *sampler) DECLSPEC_HIDDEN;
void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx,
@@ -2617,6 +2620,7 @@ struct wined3d_rendertarget_view
struct wined3d_resource *resource;
void *parent;
+ const struct wined3d_parent_ops *parent_ops;
const struct wined3d_format *format;
unsigned int sub_resource_idx;
@@ -2627,6 +2631,25 @@ struct wined3d_rendertarget_view
unsigned int depth;
};
+static inline struct wined3d_surface *wined3d_rendertarget_view_get_surface(
+ const struct wined3d_rendertarget_view *view)
+{
+ struct wined3d_resource *resource;
+ struct wined3d_texture *texture;
+
+ if (!view)
+ return NULL;
+
+ if (view->resource->type != WINED3D_RTYPE_TEXTURE && view->resource->type != WINED3D_RTYPE_CUBE_TEXTURE)
+ return NULL;
+
+ texture = wined3d_texture_from_resource(view->resource);
+ if (!(resource = wined3d_texture_get_sub_resource(texture, view->sub_resource_idx)))
+ return NULL;
+
+ return surface_from_resource(resource);
+}
+
struct wined3d_swapchain_ops
{
void (*swapchain_present)(struct wined3d_swapchain *swapchain, const RECT *src_rect,
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 216e8ab..fe3da57 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -2154,8 +2154,8 @@ struct wined3d_sampler * __cdecl wined3d_device_get_ps_sampler(const struct wine
HRESULT __cdecl wined3d_device_get_raster_status(const struct wined3d_device *device,
UINT swapchain_idx, struct wined3d_raster_status *raster_status);
DWORD __cdecl wined3d_device_get_render_state(const struct wined3d_device *device, enum wined3d_render_state state);
-struct wined3d_surface * __cdecl wined3d_device_get_render_target(const struct wined3d_device *device,
- UINT render_target_idx);
+struct wined3d_rendertarget_view * __cdecl wined3d_device_get_rendertarget_view(const struct wined3d_device *device,
+ unsigned int view_idx);
DWORD __cdecl wined3d_device_get_sampler_state(const struct wined3d_device *device,
UINT sampler_idx, enum wined3d_sampler_state state);
void __cdecl wined3d_device_get_scissor_rect(const struct wined3d_device *device, RECT *rect);
@@ -2238,8 +2238,8 @@ HRESULT __cdecl wined3d_device_set_ps_consts_i(struct wined3d_device *device,
void __cdecl wined3d_device_set_ps_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler);
void __cdecl wined3d_device_set_render_state(struct wined3d_device *device,
enum wined3d_render_state state, DWORD value);
-HRESULT __cdecl wined3d_device_set_render_target(struct wined3d_device *device,
- UINT render_target_idx, struct wined3d_surface *render_target, BOOL set_viewport);
+HRESULT __cdecl wined3d_device_set_rendertarget_view(struct wined3d_device *device,
+ unsigned int view_idx, struct wined3d_rendertarget_view *view, BOOL set_viewport);
void __cdecl wined3d_device_set_sampler_state(struct wined3d_device *device,
UINT sampler_idx, enum wined3d_sampler_state state, DWORD value);
void __cdecl wined3d_device_set_scissor_rect(struct wined3d_device *device, const RECT *rect);
@@ -2377,11 +2377,16 @@ void __cdecl wined3d_resource_set_parent(struct wined3d_resource *resource, void
DWORD __cdecl wined3d_resource_set_priority(struct wined3d_resource *resource, DWORD priority);
HRESULT __cdecl wined3d_rendertarget_view_create(const struct wined3d_rendertarget_view_desc *desc,
- struct wined3d_resource *resource, void *parent, struct wined3d_rendertarget_view **view);
+ struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
+ struct wined3d_rendertarget_view **view);
+HRESULT __cdecl wined3d_rendertarget_view_create_from_surface(struct wined3d_surface *surface,
+ void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_rendertarget_view **view);
ULONG __cdecl wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *view);
void * __cdecl wined3d_rendertarget_view_get_parent(const struct wined3d_rendertarget_view *view);
struct wined3d_resource * __cdecl wined3d_rendertarget_view_get_resource(const struct wined3d_rendertarget_view *view);
+void * __cdecl wined3d_rendertarget_view_get_sub_resource_parent(const struct wined3d_rendertarget_view *view);
ULONG __cdecl wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view *view);
+void __cdecl wined3d_rendertarget_view_set_parent(struct wined3d_rendertarget_view *view, void *parent);
HRESULT __cdecl wined3d_sampler_create(void *parent, struct wined3d_sampler **sampler);
ULONG __cdecl wined3d_sampler_decref(struct wined3d_sampler *sampler);
--
1.7.10.4
More information about the wine-patches
mailing list