[PATCH 5/5] wined3d: Update user memory for specified sub resource in wined3d_texture_update_desc().

Paul Gofman pgofman at codeweavers.com
Sun Jun 14 13:16:38 CDT 2020


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43232
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/d3d9/device.c        |  4 +-
 dlls/ddraw/surface.c      | 80 ++++++++++++++++++++++-----------------
 dlls/ddraw/tests/ddraw7.c |  4 +-
 dlls/wined3d/swapchain.c  |  4 +-
 dlls/wined3d/texture.c    | 28 ++++++++------
 dlls/wined3d/wined3d.spec |  2 +-
 include/wine/wined3d.h    |  2 +-
 7 files changed, 70 insertions(+), 54 deletions(-)

diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index 2ee582b4c54..9e0ed51894e 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -1341,7 +1341,7 @@ static HRESULT WINAPI d3d9_device_CreateTexture(IDirect3DDevice9Ex *iface,
     if (set_mem)
         wined3d_texture_update_desc(object->wined3d_texture, width, height,
                 wined3dformat_from_d3dformat(format), WINED3D_MULTISAMPLE_NONE, 0,
-                *shared_handle, 0);
+                *shared_handle, 0, 0);
 
     TRACE("Created texture %p.\n", object);
     *texture = (IDirect3DTexture9 *)&object->IDirect3DBaseTexture9_iface;
@@ -1578,7 +1578,7 @@ static HRESULT d3d9_device_create_surface(struct d3d9_device *device, unsigned i
 
     if (user_mem)
         wined3d_texture_update_desc(texture, width, height, desc.format,
-                multisample_type, multisample_quality, user_mem, 0);
+                multisample_type, multisample_quality, user_mem, 0, 0);
 
     wined3d_texture_decref(texture);
 
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index ba56fad9644..899bc77d1b9 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -4605,7 +4605,7 @@ static HRESULT WINAPI ddraw_surface1_SetClipper(IDirectDrawSurface *iface, IDire
  *****************************************************************************/
 static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags)
 {
-    struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
+    struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
     HRESULT hr;
     const DWORD allowed_flags = DDSD_LPSURFACE | DDSD_PIXELFORMAT | DDSD_WIDTH
             | DDSD_HEIGHT | DDSD_PITCH | DDSD_CAPS;
@@ -4624,9 +4624,9 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
         WARN("Flags is %x, returning DDERR_INVALIDPARAMS\n", Flags);
         return DDERR_INVALIDPARAMS;
     }
-    if (!(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
-            || This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE
-            || This->surface_desc.ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
+    if (!(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
+            || surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE
+            || surface->surface_desc.ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
     {
         WARN("Surface is not in system memory, returning DDERR_INVALIDSURFACETYPE.\n");
         return DDERR_INVALIDSURFACETYPE;
@@ -4662,10 +4662,10 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
                     DDSD->u1.lPitch, DDSD->dwWidth);
             return DDERR_INVALIDPARAMS;
         }
-        if (DDSD->dwWidth != This->surface_desc.dwWidth)
-            TRACE("Surface width changed from %u to %u.\n", This->surface_desc.dwWidth, DDSD->dwWidth);
-        if (DDSD->u1.lPitch != This->surface_desc.u1.lPitch)
-            TRACE("Surface pitch changed from %u to %u.\n", This->surface_desc.u1.lPitch, DDSD->u1.lPitch);
+        if (DDSD->dwWidth != surface->surface_desc.dwWidth)
+            TRACE("Surface width changed from %u to %u.\n", surface->surface_desc.dwWidth, DDSD->dwWidth);
+        if (DDSD->u1.lPitch != surface->surface_desc.u1.lPitch)
+            TRACE("Surface pitch changed from %u to %u.\n", surface->surface_desc.u1.lPitch, DDSD->u1.lPitch);
         pitch = DDSD->u1.lPitch;
         width = DDSD->dwWidth;
     }
@@ -4676,8 +4676,8 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
     }
     else
     {
-        pitch = This->surface_desc.u1.lPitch;
-        width = This->surface_desc.dwWidth;
+        pitch = surface->surface_desc.u1.lPitch;
+        width = surface->surface_desc.dwWidth;
     }
 
     if (DDSD->dwFlags & DDSD_HEIGHT)
@@ -4687,13 +4687,13 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
             WARN("Height is 0, returning DDERR_INVALIDPARAMS.\n");
             return DDERR_INVALIDPARAMS;
         }
-        if (DDSD->dwHeight != This->surface_desc.dwHeight)
-            TRACE("Surface height changed from %u to %u.\n", This->surface_desc.dwHeight, DDSD->dwHeight);
+        if (DDSD->dwHeight != surface->surface_desc.dwHeight)
+            TRACE("Surface height changed from %u to %u.\n", surface->surface_desc.dwHeight, DDSD->dwHeight);
         height = DDSD->dwHeight;
     }
     else
     {
-        height = This->surface_desc.dwHeight;
+        height = surface->surface_desc.dwHeight;
     }
 
     wined3d_mutex_lock();
@@ -4708,17 +4708,17 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
             wined3d_mutex_unlock();
             return DDERR_INVALIDPARAMS;
         }
-        current_format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat);
+        current_format_id = wined3dformat_from_ddrawformat(&surface->surface_desc.u4.ddpfPixelFormat);
         if (format_id != current_format_id)
             TRACE("Surface format changed from %#x to %#x.\n", current_format_id, format_id);
     }
     else
     {
-        format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat);
+        format_id = wined3dformat_from_ddrawformat(&surface->surface_desc.u4.ddpfPixelFormat);
     }
 
-    if (FAILED(hr = wined3d_texture_update_desc(This->wined3d_texture, width, height,
-            format_id, WINED3D_MULTISAMPLE_NONE, 0, DDSD->lpSurface, pitch)))
+    if (FAILED(hr = wined3d_texture_update_desc(surface->wined3d_texture, width, height,
+            format_id, WINED3D_MULTISAMPLE_NONE, 0, DDSD->lpSurface, pitch, surface->sub_resource_idx)))
     {
         WARN("Failed to update surface desc, hr %#x.\n", hr);
         wined3d_mutex_unlock();
@@ -4726,13 +4726,13 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
     }
 
     if (DDSD->dwFlags & DDSD_WIDTH)
-        This->surface_desc.dwWidth = width;
+        surface->surface_desc.dwWidth = width;
     if (DDSD->dwFlags & DDSD_PITCH)
-        This->surface_desc.u1.lPitch = DDSD->u1.lPitch;
+        surface->surface_desc.u1.lPitch = DDSD->u1.lPitch;
     if (DDSD->dwFlags & DDSD_HEIGHT)
-        This->surface_desc.dwHeight = height;
+        surface->surface_desc.dwHeight = height;
     if (DDSD->dwFlags & DDSD_PIXELFORMAT)
-        This->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat;
+        surface->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat;
 
     wined3d_mutex_unlock();
 
@@ -5854,28 +5854,40 @@ static HRESULT ddraw_surface_reserve_memory(struct wined3d_texture *wined3d_text
     static const unsigned int extra_size = 0x10000;
 
     struct ddraw_texture *texture = wined3d_texture_get_parent(wined3d_texture);
-    struct wined3d_resource_desc desc;
+    struct wined3d_resource_desc resource_desc;
+    struct wined3d_sub_resource_desc desc;
     unsigned int pitch, slice_pitch;
-    HRESULT hr;
+    unsigned int sub_resource_idx;
+    HRESULT hr = WINED3D_OK;
+    unsigned int offset;
 
-    wined3d_resource_get_desc(wined3d_texture_get_resource(wined3d_texture), &desc);
-    if (!(texture->texture_memory = heap_alloc_zero(desc.size + extra_size)))
+    wined3d_resource_get_desc(wined3d_texture_get_resource(wined3d_texture), &resource_desc);
+    if (!(texture->texture_memory = heap_alloc_zero(resource_desc.size + extra_size)))
     {
         ERR("Out of memory.\n");
         return E_OUTOFMEMORY;
     }
     TRACE("texture->texture_memory %p.\n", texture->texture_memory);
 
-    wined3d_texture_get_pitch(wined3d_texture, 0, &pitch, &slice_pitch);
-
-    if (FAILED(hr = wined3d_texture_update_desc(wined3d_texture,
-            desc.width, desc.height, desc.format,
-            WINED3D_MULTISAMPLE_NONE, 0, texture->texture_memory, pitch)))
+    offset = 0;
+    sub_resource_idx = 0;
+    while (wined3d_texture_get_sub_resource_desc(wined3d_texture, sub_resource_idx, &desc)
+            == WINED3D_OK)
     {
-        heap_free(texture->texture_memory);
-        texture->texture_memory = NULL;
-    }
+        wined3d_texture_get_pitch(wined3d_texture, sub_resource_idx, &pitch, &slice_pitch);
 
+        if (FAILED(hr = wined3d_texture_update_desc(wined3d_texture,
+                desc.width, desc.height, resource_desc.format,
+                desc.multisample_type, desc.multisample_quality,
+                (BYTE *)texture->texture_memory + offset, pitch, sub_resource_idx)))
+        {
+            heap_free(texture->texture_memory);
+            texture->texture_memory = NULL;
+            break;
+        }
+        ++sub_resource_idx;
+        offset += desc.size;
+    }
     return hr;
 }
 
@@ -6474,7 +6486,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
 
     if ((desc->dwFlags & DDSD_LPSURFACE) && FAILED(hr = wined3d_texture_update_desc(wined3d_texture,
             wined3d_desc.width, wined3d_desc.height, wined3d_desc.format,
-            WINED3D_MULTISAMPLE_NONE, 0, desc->lpSurface, pitch)))
+            WINED3D_MULTISAMPLE_NONE, 0, desc->lpSurface, pitch, 0)))
     {
         ERR("Failed to set surface memory, hr %#x.\n", hr);
         goto fail;
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index 89b5157f4dc..15f552f88e5 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -7216,12 +7216,12 @@ static void test_set_surface_desc(void)
         U1(ddsd).lPitch = 4 * 4;
         ddsd.lpSurface = data;
         hr = IDirectDrawSurface7_SetSurfaceDesc(surface2, &ddsd, 0);
-        todo_wine ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+        ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
 
         reset_ddsd(&ddsd);
         hr = IDirectDrawSurface7_Lock(surface2, NULL, &ddsd, 0, NULL);
         ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
-        todo_wine ok(ddsd.lpSurface == data, "Got unexpected lpSurface %p.\n", ddsd.lpSurface);
+        ok(ddsd.lpSurface == data, "Got unexpected lpSurface %p.\n", ddsd.lpSurface);
         IDirectDrawSurface7_Unlock(surface2, NULL);
 
         reset_ddsd(&ddsd);
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index e034bdf6241..be658cdf907 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -1927,14 +1927,14 @@ HRESULT CDECL wined3d_swapchain_resize_buffers(struct wined3d_swapchain *swapcha
 
         if (FAILED(hr = wined3d_texture_update_desc(swapchain->front_buffer, desc->backbuffer_width,
                 desc->backbuffer_height, desc->backbuffer_format,
-                desc->multisample_type, desc->multisample_quality, NULL, 0)))
+                desc->multisample_type, desc->multisample_quality, NULL, 0, 0)))
             return hr;
 
         for (i = 0; i < desc->backbuffer_count; ++i)
         {
             if (FAILED(hr = wined3d_texture_update_desc(swapchain->back_buffers[i], desc->backbuffer_width,
                     desc->backbuffer_height, desc->backbuffer_format,
-                    desc->multisample_type, desc->multisample_quality, NULL, 0)))
+                    desc->multisample_type, desc->multisample_quality, NULL, 0, 0)))
                 return hr;
         }
     }
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 76291368558..a740645d46c 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -1744,7 +1744,7 @@ void wined3d_texture_gl_set_compatible_renderbuffer(struct wined3d_texture_gl *t
 
 HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT width, UINT height,
         enum wined3d_format_id format_id, enum wined3d_multisample_type multisample_type,
-        UINT multisample_quality, void *mem, UINT pitch)
+        UINT multisample_quality, void *mem, UINT pitch, unsigned int sub_resource_idx)
 {
     struct wined3d_texture_sub_resource *sub_resource;
     const struct wined3d_d3d_info *d3d_info;
@@ -1757,10 +1757,12 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
     DWORD valid_location = 0;
     bool update_memory_only;
     bool create_dib = false;
+    unsigned int level;
 
     TRACE("texture %p, width %u, height %u, format %s, multisample_type %#x, multisample_quality %u, "
-            "mem %p, pitch %u.\n",
-            texture, width, height, debug_d3dformat(format_id), multisample_type, multisample_quality, mem, pitch);
+            "mem %p, pitch %u, sub_resource_idx %u.\n",
+            texture, width, height, debug_d3dformat(format_id), multisample_type, multisample_quality, mem, pitch,
+            sub_resource_idx);
 
     device = texture->resource.device;
     d3d = device->wined3d;
@@ -1768,8 +1770,10 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
     d3d_info = &device->adapter->d3d_info;
     format = wined3d_get_format(device->adapter, format_id, texture->resource.bind_flags);
     resource_size = wined3d_format_calculate_size(format, device->surface_alignment, width, height, 1);
+    level = sub_resource_idx % texture->level_count;
 
-    update_memory_only = width == texture->resource.width && height == texture->resource.height
+    update_memory_only = width == wined3d_texture_get_level_width(texture, level)
+            && height == wined3d_texture_get_level_height(texture, level)
             && format_id == texture->resource.format->id && multisample_type == texture->resource.multisample_type
             && multisample_quality == texture->resource.multisample_quality;
 
@@ -1782,7 +1786,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
     {
         unsigned int current_row_pitch, current_slice_pitch;
 
-        wined3d_texture_get_pitch(texture, 0, &current_row_pitch, &current_slice_pitch);
+        wined3d_texture_get_pitch(texture, level, &current_row_pitch, &current_slice_pitch);
         update_memory_only = pitch == current_row_pitch && slice_pitch == current_slice_pitch;
     }
 
@@ -1791,7 +1795,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
 
     if (texture->level_count * texture->layer_count > 1 && !update_memory_only)
     {
-        WARN("Texture has multiple sub-resources, not supported.\n");
+        FIXME("Texture has multiple sub-resources, not supported.\n");
         return WINED3DERR_INVALIDCALL;
     }
 
@@ -1826,7 +1830,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
 
     if (texture->dc_info && texture->dc_info[0].dc)
     {
-        struct wined3d_texture_idx texture_idx = {texture, 0};
+        struct wined3d_texture_idx texture_idx = {texture, sub_resource_idx};
 
         wined3d_cs_destroy_object(device->cs, wined3d_texture_destroy_dc, &texture_idx);
         wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
@@ -1838,7 +1842,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
 
     if (!update_memory_only)
     {
-        sub_resource = &texture->sub_resources[0];
+        sub_resource = &texture->sub_resources[sub_resource_idx];
 
         texture->row_pitch = pitch;
         texture->slice_pitch = slice_pitch;
@@ -1886,7 +1890,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
         }
     }
 
-    if ((texture->sub_resources[0].user_memory = mem))
+    if ((texture->sub_resources[sub_resource_idx].user_memory = mem))
     {
         texture->resource.map_binding = WINED3D_LOCATION_USER_MEMORY;
         valid_location = WINED3D_LOCATION_USER_MEMORY;
@@ -1905,12 +1909,12 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
     if (texture->resource.map_binding == WINED3D_LOCATION_BUFFER && !wined3d_texture_use_pbo(texture, gl_info))
         texture->resource.map_binding = WINED3D_LOCATION_SYSMEM;
 
-    wined3d_texture_validate_location(texture, 0, valid_location);
-    wined3d_texture_invalidate_location(texture, 0, ~valid_location);
+    wined3d_texture_validate_location(texture, sub_resource_idx, valid_location);
+    wined3d_texture_invalidate_location(texture, sub_resource_idx, ~valid_location);
 
     if (create_dib)
     {
-        struct wined3d_texture_idx texture_idx = {texture, 0};
+        struct wined3d_texture_idx texture_idx = {texture, sub_resource_idx};
 
         wined3d_cs_init_object(device->cs, wined3d_texture_create_dc, &texture_idx);
         wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index f4a648cac8b..75ce68119d7 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -307,7 +307,7 @@
 @ cdecl wined3d_texture_set_lod(ptr long)
 @ cdecl wined3d_texture_set_overlay_position(ptr long long long)
 @ cdecl wined3d_texture_set_sub_resource_parent(ptr long ptr)
-@ cdecl wined3d_texture_update_desc(ptr long long long long long ptr long)
+@ cdecl wined3d_texture_update_desc(ptr long long long long long ptr long long)
 @ cdecl wined3d_texture_update_overlay(ptr long ptr ptr long ptr long)
 
 @ cdecl wined3d_unordered_access_view_create(ptr ptr ptr ptr ptr)
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 5450b4d2117..07e6833402a 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -2811,7 +2811,7 @@ void __cdecl wined3d_texture_set_sub_resource_parent(struct wined3d_texture *tex
 HRESULT __cdecl wined3d_texture_update_desc(struct wined3d_texture *texture,
         UINT width, UINT height, enum wined3d_format_id format_id,
         enum wined3d_multisample_type multisample_type, UINT multisample_quality,
-        void *mem, UINT pitch);
+        void *mem, UINT pitch, unsigned int sub_resource_idx);
 HRESULT __cdecl wined3d_texture_update_overlay(struct wined3d_texture *texture, unsigned int sub_resource_idx,
         const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
         const RECT *dst_rect, DWORD flags);
-- 
2.26.2




More information about the wine-devel mailing list