[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