[PATCH v2] wined3d: Allow setting user memory for mipmapped texture in wined3d_texture_update_desc().

Paul Gofman pgofman at codeweavers.com
Thu May 7 04:23:45 CDT 2020


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49105
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
v2:
    - fix test failure on some testbot machines.

 dlls/ddraw/tests/ddraw7.c |  38 ++++++++++++---
 dlls/wined3d/texture.c    | 100 +++++++++++++++++++++-----------------
 2 files changed, 86 insertions(+), 52 deletions(-)

diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index 1ddd3cdb0e..240438d098 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -13347,14 +13347,14 @@ static void test_display_mode_surface_pixel_format(void)
 
     surface_desc.dwSize = sizeof(surface_desc);
     hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
-    ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
     width = surface_desc.dwWidth;
     height = surface_desc.dwHeight;
 
     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
             0, 0, width, height, NULL, NULL, NULL, NULL);
     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
-    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
 
     bpp = 0;
     if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 16, 0, 0)))
@@ -13367,7 +13367,7 @@ static void test_display_mode_surface_pixel_format(void)
 
     surface_desc.dwSize = sizeof(surface_desc);
     hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
-    ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
     ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
     ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
     ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
@@ -13379,9 +13379,9 @@ static void test_display_mode_surface_pixel_format(void)
     U5(surface_desc).dwBackBufferCount = 1;
     surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
     hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
-    ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
     hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
-    ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
     ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
     ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
     ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
@@ -13397,15 +13397,39 @@ static void test_display_mode_surface_pixel_format(void)
     surface_desc.dwHeight = height;
     surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
     hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
-    ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
     hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
-    ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
     ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
             U4(surface_desc).ddpfPixelFormat.dwFlags);
     ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
             U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
     IDirectDrawSurface7_Release(surface);
 
+    /* Test compatibility mode mipmap texture creation. */
+    hr = IDirectDraw7_SetDisplayMode(ddraw, width, height, 16, 0, 0);
+    ok(hr == D3D_OK || hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
+    if (FAILED(hr))
+    {
+        win_skip("SetDisplayMode failed, skipping test.");
+        goto done;
+    }
+    bpp = 16;
+
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT | DDSD_PITCH;
+    U2(surface_desc).dwMipMapCount = 2;
+    surface_desc.dwWidth = 4;
+    surface_desc.dwHeight = 4;
+    U1(surface_desc).lPitch = surface_desc.dwWidth * bpp / 8;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_VIDEOMEMORY;
+    hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == D3D_OK || hr == DDERR_NODIRECTDRAWHW, "Got unexpected hr %#x.\n", hr);
+    if (surface)
+        IDirectDrawSurface7_Release(surface);
+
+done:
     refcount = IDirectDraw7_Release(ddraw);
     ok(!refcount, "DirectDraw has %u references left.\n", refcount);
     DestroyWindow(window);
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 49373eb58a..239c089dd8 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -1748,9 +1748,10 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
     const struct wined3d_d3d_info *d3d_info;
     const struct wined3d_gl_info *gl_info;
     const struct wined3d_format *format;
-    const struct wined3d *d3d;
     struct wined3d_device *device;
     unsigned int resource_size;
+    const struct wined3d *d3d;
+    BOOL set_user_memory_only;
     DWORD valid_location = 0;
     BOOL create_dib = FALSE;
 
@@ -1765,10 +1766,15 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
     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);
 
+    set_user_memory_only = width == texture->resource.width && height == texture->resource.height
+            && format_id == texture->resource.format->id && multisample_type == texture->resource.multisample_type
+            && multisample_quality == texture->resource.multisample_quality
+            && (!texture->row_pitch || pitch == texture->row_pitch);
+
     if (!resource_size)
         return WINED3DERR_INVALIDCALL;
 
-    if (texture->level_count * texture->layer_count > 1)
+    if (texture->level_count * texture->layer_count > 1 && !set_user_memory_only)
     {
         WARN("Texture has multiple sub-resources, not supported.\n");
         return WINED3DERR_INVALIDCALL;
@@ -1803,7 +1809,6 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
         wined3d_cs_emit_unload_resource(device->cs, &texture->resource);
     wined3d_resource_wait_idle(&texture->resource);
 
-    sub_resource = &texture->sub_resources[0];
     if (texture->dc_info && texture->dc_info[0].dc)
     {
         struct wined3d_texture_idx texture_idx = {texture, 0};
@@ -1815,55 +1820,60 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
 
     wined3d_resource_free_sysmem(&texture->resource);
 
-    if ((texture->row_pitch = pitch))
-        texture->slice_pitch = height * pitch;
-    else
-        /* User memory surfaces don't have the regular surface alignment. */
-        wined3d_format_calculate_pitch(format, 1, width, height,
-                &texture->row_pitch, &texture->slice_pitch);
-
-    texture->resource.format = format;
-    texture->resource.multisample_type = multisample_type;
-    texture->resource.multisample_quality = multisample_quality;
-    texture->resource.width = width;
-    texture->resource.height = height;
-    if (!(texture->resource.access & WINED3D_RESOURCE_ACCESS_CPU) && d3d->flags & WINED3D_VIDMEM_ACCOUNTING)
-        adapter_adjust_memory(device->adapter,  (INT64)texture->slice_pitch - texture->resource.size);
-    texture->resource.size = texture->slice_pitch;
-    sub_resource->size = texture->slice_pitch;
-    sub_resource->locations = WINED3D_LOCATION_DISCARDED;
-
-    if (texture->texture_ops == &texture_gl_ops)
-    {
-        if (multisample_type && gl_info->supported[ARB_TEXTURE_MULTISAMPLE])
+    if (!set_user_memory_only)
+    {
+        sub_resource = &texture->sub_resources[0];
+
+        if ((texture->row_pitch = pitch))
+            texture->slice_pitch = height * pitch;
+        else
+            /* User memory surfaces don't have the regular surface alignment. */
+            wined3d_format_calculate_pitch(format, 1, width, height,
+                    &texture->row_pitch, &texture->slice_pitch);
+
+        texture->resource.format = format;
+        texture->resource.multisample_type = multisample_type;
+        texture->resource.multisample_quality = multisample_quality;
+        texture->resource.width = width;
+        texture->resource.height = height;
+        if (!(texture->resource.access & WINED3D_RESOURCE_ACCESS_CPU) && d3d->flags & WINED3D_VIDMEM_ACCOUNTING)
+            adapter_adjust_memory(device->adapter,  (INT64)texture->slice_pitch - texture->resource.size);
+        texture->resource.size = texture->slice_pitch;
+        sub_resource->size = texture->slice_pitch;
+        sub_resource->locations = WINED3D_LOCATION_DISCARDED;
+
+        if (texture->texture_ops == &texture_gl_ops)
+        {
+            if (multisample_type && gl_info->supported[ARB_TEXTURE_MULTISAMPLE])
+            {
+                wined3d_texture_gl(texture)->target = GL_TEXTURE_2D_MULTISAMPLE;
+                texture->flags &= ~WINED3D_TEXTURE_DOWNLOADABLE;
+            }
+            else
+            {
+                wined3d_texture_gl(texture)->target = GL_TEXTURE_2D;
+                texture->flags |= WINED3D_TEXTURE_DOWNLOADABLE;
+            }
+        }
+
+        if (((width & (width - 1)) || (height & (height - 1))) && !d3d_info->texture_npot
+                && !d3d_info->texture_npot_conditional)
         {
-            wined3d_texture_gl(texture)->target = GL_TEXTURE_2D_MULTISAMPLE;
-            texture->flags &= ~WINED3D_TEXTURE_DOWNLOADABLE;
+            texture->flags |= WINED3D_TEXTURE_COND_NP2_EMULATED;
+            texture->pow2_width = texture->pow2_height = 1;
+            while (texture->pow2_width < width)
+                texture->pow2_width <<= 1;
+            while (texture->pow2_height < height)
+                texture->pow2_height <<= 1;
         }
         else
         {
-            wined3d_texture_gl(texture)->target = GL_TEXTURE_2D;
-            texture->flags |= WINED3D_TEXTURE_DOWNLOADABLE;
+            texture->flags &= ~WINED3D_TEXTURE_COND_NP2_EMULATED;
+            texture->pow2_width = width;
+            texture->pow2_height = height;
         }
     }
 
-    if (((width & (width - 1)) || (height & (height - 1))) && !d3d_info->texture_npot
-            && !d3d_info->texture_npot_conditional)
-    {
-        texture->flags |= WINED3D_TEXTURE_COND_NP2_EMULATED;
-        texture->pow2_width = texture->pow2_height = 1;
-        while (texture->pow2_width < width)
-            texture->pow2_width <<= 1;
-        while (texture->pow2_height < height)
-            texture->pow2_height <<= 1;
-    }
-    else
-    {
-        texture->flags &= ~WINED3D_TEXTURE_COND_NP2_EMULATED;
-        texture->pow2_width = width;
-        texture->pow2_height = height;
-    }
-
     if ((texture->user_memory = mem))
     {
         texture->resource.map_binding = WINED3D_LOCATION_USER_MEMORY;
-- 
2.26.2




More information about the wine-devel mailing list