[PATCH 04/11] ddraw: Create the second texture for system memory bindable surfaces.

Paul Gofman pgofman at codeweavers.com
Wed Mar 3 16:35:34 CST 2021


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/ddraw/ddraw_private.h |  18 +++++
 dlls/ddraw/device.c        |  60 ++++++++++++++++-
 dlls/ddraw/executebuffer.c |   6 ++
 dlls/ddraw/surface.c       | 134 ++++++++++++++++++++++++++++++++++---
 4 files changed, 206 insertions(+), 12 deletions(-)

diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index e25ab23c2bc..432e28065e0 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -176,6 +176,7 @@ struct ddraw_surface
     /* Connections to other Objects */
     struct ddraw *ddraw;
     struct wined3d_texture *wined3d_texture;
+    struct wined3d_texture *draw_texture;
     unsigned int sub_resource_idx;
     struct wined3d_rendertarget_view *wined3d_rtv;
     struct wined3d_private_store private_store;
@@ -653,6 +654,23 @@ static inline BOOL ddraw_surface_can_be_lost(const struct ddraw_surface *surface
     return surface->sysmem_fallback;
 }
 
+static inline void d3d_surface_sync_textures(struct ddraw_surface *surface, BOOL upload)
+{
+    if (!surface->draw_texture)
+        return;
+
+    if (upload)
+        wined3d_device_copy_sub_resource_region(surface->ddraw->wined3d_device,
+                wined3d_texture_get_resource(surface->draw_texture), surface->sub_resource_idx, 0, 0, 0,
+                wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx, NULL, 0);
+    else
+        wined3d_device_copy_sub_resource_region(surface->ddraw->wined3d_device,
+                wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx, 0, 0, 0,
+                wined3d_texture_get_resource(surface->draw_texture), surface->sub_resource_idx, NULL, 0);
+}
+
+void d3d_device_sync_surfaces(struct d3d_device *device, BOOL upload) DECLSPEC_HIDDEN;
+
 /* Used for generic dumping */
 struct flag_info
 {
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c
index 5e66007213d..e4822e5d29e 100644
--- a/dlls/ddraw/device.c
+++ b/dlls/ddraw/device.c
@@ -3427,6 +3427,47 @@ static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT
     return D3D_OK;
 }
 
+static void d3d_device_sync_rendertarget(struct d3d_device *device, BOOL upload)
+{
+    struct wined3d_rendertarget_view *rtv;
+
+    if (device->hardware_device)
+        return;
+
+    if ((rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
+        d3d_surface_sync_textures(wined3d_rendertarget_view_get_parent(rtv), upload);
+
+    if ((rtv = wined3d_device_get_depth_stencil_view(device->wined3d_device)))
+        d3d_surface_sync_textures(wined3d_rendertarget_view_get_parent(rtv), upload);
+}
+
+void d3d_device_sync_surfaces(struct d3d_device *device, BOOL upload)
+{
+    const struct wined3d_stateblock_state *state = device->stateblock_state;
+    struct ddraw_surface *surface;
+    unsigned int i, j;
+
+    if (device->hardware_device)
+        return;
+
+    d3d_device_sync_rendertarget(device, upload);
+
+    for (i = 0; i < ARRAY_SIZE(state->textures); ++i)
+    {
+        if (!state->textures[i])
+            continue;
+
+        j = 0;
+        while ((surface = wined3d_texture_get_sub_resource_parent(state->textures[i], j)))
+        {
+            if (!surface->draw_texture)
+                break;
+            d3d_surface_sync_textures(surface, upload);
+            ++j;
+        }
+    }
+}
+
 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
         D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
         DWORD vertex_count, DWORD flags)
@@ -3481,7 +3522,9 @@ static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
     wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf));
     wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
     wined3d_device_apply_stateblock(device->wined3d_device, device->state);
+    d3d_device_sync_surfaces(device, TRUE);
     hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
+    d3d_device_sync_surfaces(device, FALSE);
 
 done:
     wined3d_mutex_unlock();
@@ -3693,7 +3736,9 @@ static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
     wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
     wined3d_stateblock_set_base_vertex_index(device->state, vb_pos / stride);
     wined3d_device_apply_stateblock(device->wined3d_device, device->state);
+    d3d_device_sync_surfaces(device, TRUE);
     hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
+    d3d_device_sync_surfaces(device, FALSE);
 
 done:
     wined3d_mutex_unlock();
@@ -4019,7 +4064,9 @@ static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIM
 
     wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
     wined3d_device_apply_stateblock(device->wined3d_device, device->state);
+    d3d_device_sync_surfaces(device, TRUE);
     hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, vertex_count);
+    d3d_device_sync_surfaces(device, FALSE);
 
 done:
     wined3d_mutex_unlock();
@@ -4155,7 +4202,9 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
     wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf));
     wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
     wined3d_device_apply_stateblock(device->wined3d_device, device->state);
+    d3d_device_sync_surfaces(device, TRUE);
     hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
+    d3d_device_sync_surfaces(device, FALSE);
 
 done:
     wined3d_mutex_unlock();
@@ -4277,7 +4326,9 @@ static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVE
     /* Now draw the primitives */
     wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
     wined3d_device_apply_stateblock(device->wined3d_device, device->state);
+    d3d_device_sync_surfaces(device, TRUE);
     hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, vertex_count);
+    d3d_device_sync_surfaces(device, FALSE);
 
     wined3d_mutex_unlock();
 
@@ -4431,7 +4482,9 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
 
     wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
     wined3d_device_apply_stateblock(device->wined3d_device, device->state);
+    d3d_device_sync_surfaces(device, TRUE);
     hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
+    d3d_device_sync_surfaces(device, FALSE);
 
     wined3d_mutex_unlock();
 
@@ -4778,7 +4831,7 @@ static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
     TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
 
     if (surf && (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
-        wined3d_texture = surf->wined3d_texture;
+        wined3d_texture = surf->draw_texture ? surf->draw_texture : surf->wined3d_texture;
 
     wined3d_mutex_lock();
     wined3d_stateblock_set_texture(device->update_state, stage, wined3d_texture);
@@ -5270,7 +5323,9 @@ static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
 
     wined3d_mutex_lock();
     wined3d_device_apply_stateblock(device->wined3d_device, device->state);
+    d3d_device_sync_rendertarget(device, TRUE);
     hr = wined3d_device_clear(device->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
+    d3d_device_sync_rendertarget(device, FALSE);
     wined3d_mutex_unlock();
 
     return hr;
@@ -5732,7 +5787,8 @@ static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7
         return DDERR_INVALIDPARAMS;
 
     wined3d_mutex_lock();
-    wined3d_resource_preload(wined3d_texture_get_resource(surface->wined3d_texture));
+    wined3d_resource_preload(wined3d_texture_get_resource(surface->draw_texture ? surface->draw_texture
+            : surface->wined3d_texture));
     wined3d_mutex_unlock();
 
     return D3D_OK;
diff --git a/dlls/ddraw/executebuffer.c b/dlls/ddraw/executebuffer.c
index e0a9445bf71..6900059b05f 100644
--- a/dlls/ddraw/executebuffer.c
+++ b/dlls/ddraw/executebuffer.c
@@ -81,8 +81,10 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer, struct d3d
                         ddraw_find_decl(device->ddraw, D3DFVF_TLVERTEX));
 
                 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
+                d3d_device_sync_surfaces(device, TRUE);
                 for (i = 0; i < count; ++i)
                     wined3d_device_draw_primitive(device->wined3d_device, p[i].wFirst, p[i].wCount);
+                d3d_device_sync_surfaces(device, FALSE);
 
                 instr += sizeof(*p) * count;
                 break;
@@ -189,7 +191,9 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer, struct d3d
                         ddraw_find_decl(device->ddraw, D3DFVF_TLVERTEX));
                 wined3d_stateblock_set_index_buffer(device->state, buffer->index_buffer, WINED3DFMT_R16_UINT);
                 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
+                d3d_device_sync_surfaces(device, TRUE);
                 wined3d_device_draw_indexed_primitive(device->wined3d_device, index_pos, index_count);
+                d3d_device_sync_surfaces(device, FALSE);
 
                 buffer->index_pos = index_pos + index_count;
                 break;
@@ -310,8 +314,10 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer, struct d3d
                                     ddraw_find_decl(device->ddraw, op == D3DPROCESSVERTICES_TRANSFORMLIGHT
                                     ? D3DFVF_VERTEX : D3DFVF_LVERTEX));
                             wined3d_device_apply_stateblock(device->wined3d_device, device->state);
+                            d3d_device_sync_surfaces(device, TRUE);
                             wined3d_device_process_vertices(device->wined3d_device, ci->wStart, ci->wDest,
                                     ci->dwCount, buffer->dst_vertex_buffer, NULL, 0, D3DFVF_TLVERTEX);
+                            d3d_device_sync_surfaces(device, FALSE);
                             break;
 
                         case D3DPROCESSVERTICES_COPY:
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index b910fb6817e..d22ca2e5136 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -1307,7 +1307,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface *
     struct ddraw_texture *dst_ddraw_texture, *src_ddraw_texture;
     struct wined3d_rendertarget_view *tmp_rtv, *src_rtv, *rtv;
     DDSCAPS caps = {DDSCAPS_FLIP};
-    struct wined3d_texture *texture;
+    struct wined3d_texture *texture, *draw_texture;
     IDirectDrawSurface *current;
     void *texture_memory;
     HRESULT hr;
@@ -1337,6 +1337,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface *
     rtv = wined3d_device_get_rendertarget_view(dst_impl->ddraw->wined3d_device, 0);
     dst_ddraw_texture = wined3d_texture_get_parent(dst_impl->wined3d_texture);
     texture_memory = dst_ddraw_texture->texture_memory;
+    draw_texture = dst_impl->draw_texture;
 
     if (src_impl)
     {
@@ -1363,13 +1364,18 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface *
         wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
         dst_impl->wined3d_rtv = src_rtv;
         wined3d_texture_set_sub_resource_parent(src_impl->wined3d_texture, 0, dst_impl);
+        if (src_impl->draw_texture)
+            wined3d_texture_set_sub_resource_parent(src_impl->draw_texture, 0, dst_impl);
         src_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
         dst_ddraw_texture->texture_memory = src_ddraw_texture->texture_memory;
         wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), dst_ddraw_texture);
+        if (src_impl->draw_texture)
+            wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->draw_texture), dst_ddraw_texture);
         dst_ddraw_texture = src_ddraw_texture;
         if (src_impl->sub_resource_idx)
             ERR("Invalid sub-resource index %u on surface %p.\n", src_impl->sub_resource_idx, src_impl);
         dst_impl->wined3d_texture = src_impl->wined3d_texture;
+        dst_impl->draw_texture = src_impl->draw_texture;
     }
     else
     {
@@ -1395,13 +1401,18 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface *
             wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
             dst_impl->wined3d_rtv = src_rtv;
             wined3d_texture_set_sub_resource_parent(src_impl->wined3d_texture, 0, dst_impl);
+            if (src_impl->draw_texture)
+                wined3d_texture_set_sub_resource_parent(src_impl->draw_texture, 0, dst_impl);
             src_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
             dst_ddraw_texture->texture_memory = src_ddraw_texture->texture_memory;
             wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), dst_ddraw_texture);
+            if (src_impl->draw_texture)
+                wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->draw_texture), dst_ddraw_texture);
             dst_ddraw_texture = src_ddraw_texture;
             if (src_impl->sub_resource_idx)
                 ERR("Invalid sub-resource index %u on surface %p.\n", src_impl->sub_resource_idx, src_impl);
             dst_impl->wined3d_texture = src_impl->wined3d_texture;
+            dst_impl->draw_texture = src_impl->draw_texture;
             dst_impl = src_impl;
         }
     }
@@ -1413,9 +1424,14 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface *
     wined3d_rendertarget_view_set_parent(tmp_rtv, src_impl);
     src_impl->wined3d_rtv = tmp_rtv;
     wined3d_texture_set_sub_resource_parent(texture, 0, src_impl);
+    if (draw_texture)
+        wined3d_texture_set_sub_resource_parent(draw_texture, 0, src_impl);
     dst_ddraw_texture->texture_memory = texture_memory;
     wined3d_resource_set_parent(wined3d_texture_get_resource(texture), dst_ddraw_texture);
+    if (draw_texture)
+        wined3d_resource_set_parent(wined3d_texture_get_resource(draw_texture), dst_ddraw_texture);
     src_impl->wined3d_texture = texture;
+    src_impl->draw_texture = draw_texture;
 
     if (flags & ~(DDFLIP_NOVSYNC | DDFLIP_INTERVAL2 | DDFLIP_INTERVAL3 | DDFLIP_INTERVAL4))
     {
@@ -1491,6 +1507,7 @@ static HRESULT ddraw_surface_blt(struct ddraw_surface *dst_surface, const RECT *
     struct wined3d_device *wined3d_device = dst_surface->ddraw->wined3d_device;
     struct wined3d_color colour;
     DWORD wined3d_flags;
+    HRESULT hr;
 
     if (flags & DDBLT_COLORFILL)
     {
@@ -1503,9 +1520,12 @@ static HRESULT ddraw_surface_blt(struct ddraw_surface *dst_surface, const RECT *
             return DDERR_INVALIDPARAMS;
 
         wined3d_device_apply_stateblock(wined3d_device, dst_surface->ddraw->state);
-        return wined3d_device_clear_rendertarget_view(wined3d_device,
+        d3d_surface_sync_textures(dst_surface, TRUE);
+        hr = wined3d_device_clear_rendertarget_view(wined3d_device,
                 ddraw_surface_get_rendertarget_view(dst_surface),
                 dst_rect, wined3d_flags, &colour, 0.0f, 0);
+        d3d_surface_sync_textures(dst_surface, FALSE);
+        return hr;
     }
 
     if (flags & DDBLT_DEPTHFILL)
@@ -1519,9 +1539,12 @@ static HRESULT ddraw_surface_blt(struct ddraw_surface *dst_surface, const RECT *
             return DDERR_INVALIDPARAMS;
 
         wined3d_device_apply_stateblock(wined3d_device, dst_surface->ddraw->state);
-        return wined3d_device_clear_rendertarget_view(wined3d_device,
+        d3d_surface_sync_textures(dst_surface, TRUE);
+        hr = wined3d_device_clear_rendertarget_view(wined3d_device,
                 ddraw_surface_get_rendertarget_view(dst_surface),
                 dst_rect, wined3d_flags, NULL, colour.r, 0);
+        d3d_surface_sync_textures(dst_surface, FALSE);
+        return hr;
     }
 
     wined3d_flags = flags & ~DDBLT_ASYNC;
@@ -2551,6 +2574,9 @@ static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWO
     {
         resource = wined3d_texture_get_resource(surface->wined3d_texture);
         wined3d_resource_set_priority(resource, priority);
+        if (surface->draw_texture)
+            wined3d_resource_set_priority(wined3d_texture_get_resource(surface->draw_texture), priority);
+
         hr = DD_OK;
     }
     wined3d_mutex_unlock();
@@ -4267,6 +4293,8 @@ static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD Ma
     }
 
     hr = wined3d_texture_set_lod(surface->wined3d_texture, MaxLOD);
+    if (SUCCEEDED(hr) && surface->draw_texture)
+        hr = wined3d_texture_set_lod(surface->draw_texture, MaxLOD);
     wined3d_mutex_unlock();
 
     return hr;
@@ -4736,6 +4764,14 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
         return hr_ddraw_from_wined3d(hr);
     }
 
+    if (surface->draw_texture && FAILED(hr = wined3d_texture_update_desc(surface->draw_texture,
+            surface->sub_resource_idx, width, height, format_id, WINED3D_MULTISAMPLE_NONE, 0, NULL, 0)))
+    {
+        ERR("Failed to update surface desc for draw_texture, hr %#x.\n", hr);
+        wined3d_mutex_unlock();
+        return hr_ddraw_from_wined3d(hr);
+    }
+
     if (DDSD->dwFlags & DDSD_WIDTH)
         surface->surface_desc.dwWidth = width;
     if (DDSD->dwFlags & DDSD_PITCH)
@@ -4842,6 +4878,18 @@ static HRESULT WINAPI ddraw_surface1_GetPalette(IDirectDrawSurface *iface, IDire
     return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
 }
 
+static HRESULT ddraw_surface_set_wined3d_textures_colour_key(struct ddraw_surface *surface, DWORD flags,
+        struct wined3d_color_key *color_key)
+{
+    HRESULT hr;
+
+    hr = wined3d_texture_set_color_key(surface->wined3d_texture, flags, color_key);
+    if (surface->draw_texture && SUCCEEDED(hr))
+        hr = wined3d_texture_set_color_key(surface->draw_texture, flags, color_key);
+
+    return hr;
+}
+
 static HRESULT ddraw_surface_set_color_key(struct ddraw_surface *surface, DWORD flags, DDCOLORKEY *color_key)
 {
     DDCOLORKEY fixed_color_key;
@@ -4916,7 +4964,7 @@ static HRESULT ddraw_surface_set_color_key(struct ddraw_surface *surface, DWORD
     }
 
     if (surface->is_complex_root)
-        hr = wined3d_texture_set_color_key(surface->wined3d_texture, flags,
+        hr = ddraw_surface_set_wined3d_textures_colour_key(surface, flags,
                 color_key ? (struct wined3d_color_key *)&fixed_color_key : NULL);
 
     wined3d_mutex_unlock();
@@ -5832,6 +5880,9 @@ static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *paren
 
     wined3d_private_store_cleanup(&surface->private_store);
 
+    if (surface->draw_texture)
+        wined3d_texture_decref(surface->draw_texture);
+
     heap_free(surface);
 }
 
@@ -5902,6 +5953,65 @@ static HRESULT ddraw_surface_reserve_memory(struct wined3d_texture *wined3d_text
     return hr;
 }
 
+static void ddraw_surface_create_draw_texture(struct ddraw_surface *surface)
+{
+    DDSURFACEDESC2 *desc = &surface->surface_desc;
+    struct wined3d_resource *draw_texture_resource;
+    struct wined3d_resource_desc wined3d_desc;
+    unsigned int i, layer_count, level_count;
+    struct wined3d_texture *draw_texture;
+    struct ddraw_surface *parent;
+    unsigned int bind_flags;
+    HRESULT hr;
+
+    if (!(desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
+        return;
+
+    bind_flags = 0;
+    if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
+            || (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
+        bind_flags |= WINED3D_BIND_SHADER_RESOURCE;
+
+    if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
+        bind_flags |= WINED3D_BIND_DEPTH_STENCIL;
+    else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
+        bind_flags |= WINED3D_BIND_RENDER_TARGET;
+
+    if (!bind_flags)
+        return;
+
+    layer_count = surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP ? 6 : 1;
+    level_count = wined3d_texture_get_level_count(surface->wined3d_texture);
+
+    draw_texture_resource = wined3d_texture_get_resource(surface->wined3d_texture);
+    wined3d_resource_get_desc(draw_texture_resource, &wined3d_desc);
+
+    wined3d_desc.bind_flags = bind_flags;
+    wined3d_desc.access = WINED3D_RESOURCE_ACCESS_GPU;
+
+    if (FAILED(hr = wined3d_texture_create(surface->ddraw->wined3d_device, &wined3d_desc, layer_count,
+            level_count, 0, NULL, NULL,
+            &ddraw_null_wined3d_parent_ops, &draw_texture)))
+    {
+        WARN("Failed to create wined3d texture, hr %#x.\n", hr);
+        return;
+    }
+
+    wined3d_resource_set_parent(draw_texture_resource, wined3d_texture_get_parent(surface->wined3d_texture));
+
+    i = 0;
+    while ((parent = wined3d_texture_get_sub_resource_parent(surface->wined3d_texture, i)))
+    {
+        wined3d_texture_set_sub_resource_parent(draw_texture, i, parent);
+        wined3d_texture_incref(parent->draw_texture = draw_texture);
+        ++i;
+    }
+    assert(surface->draw_texture);
+
+    wined3d_texture_decref(draw_texture);
+    TRACE("Surface %p, created draw_texture %p.\n", surface, draw_texture);
+}
+
 HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc,
         struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version)
 {
@@ -6416,22 +6526,24 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
 
     root = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0);
     wined3d_texture_decref(wined3d_texture);
+    ddraw_surface_create_draw_texture(root);
+
     root->is_complex_root = TRUE;
     root->sysmem_fallback = sysmem_fallback;
     texture->root = root;
     wined3d_device_incref(texture->wined3d_device = ddraw->wined3d_device);
 
     if (desc->dwFlags & DDSD_CKDESTOVERLAY)
-        wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY,
+        ddraw_surface_set_wined3d_textures_colour_key(root, DDCKEY_DESTOVERLAY,
                 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
     if (desc->dwFlags & DDSD_CKDESTBLT)
-        wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT,
+        ddraw_surface_set_wined3d_textures_colour_key(root, DDCKEY_DESTBLT,
                 (struct wined3d_color_key *)&desc->ddckCKDestBlt);
     if (desc->dwFlags & DDSD_CKSRCOVERLAY)
-        wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY,
+        ddraw_surface_set_wined3d_textures_colour_key(root, DDCKEY_SRCOVERLAY,
                 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
     if (desc->dwFlags & DDSD_CKSRCBLT)
-        wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT,
+        ddraw_surface_set_wined3d_textures_colour_key(root, DDCKEY_SRCBLT,
                 (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
 
     for (i = 0; i < layers; ++i)
@@ -6573,7 +6685,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
                 hr = hr_ddraw_from_wined3d(hr);
                 goto fail;
             }
-
+            ddraw_surface_create_draw_texture(last);
             *attach = last;
             attach = &last->complex_array[0];
         }
@@ -6690,12 +6802,14 @@ static const struct wined3d_parent_ops ddraw_view_wined3d_parent_ops =
 
 struct wined3d_rendertarget_view *ddraw_surface_get_rendertarget_view(struct ddraw_surface *surface)
 {
+    struct wined3d_texture *wined3d_texture;
     HRESULT hr;
 
     if (surface->wined3d_rtv)
         return surface->wined3d_rtv;
 
-    if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(surface->wined3d_texture,
+    wined3d_texture = surface->draw_texture ? surface->draw_texture : surface->wined3d_texture;
+    if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(wined3d_texture,
             surface->sub_resource_idx, surface, &ddraw_view_wined3d_parent_ops, &surface->wined3d_rtv)))
     {
         ERR("Failed to create rendertarget view, hr %#x.\n", hr);
-- 
2.29.2




More information about the wine-devel mailing list