Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49105 Signed-off-by: Paul Gofman pgofman@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;
On Thu, 7 May 2020 at 13:54, Paul Gofman pgofman@codeweavers.com wrote:
- 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);
The pitch handling doesn't seem quite right. I.e., if texture->row_pitch is currently 0 (default), it effectively has the value calculated by wined3d_format_calculate_pitch() with the default alignment. That's potentially different from "pitch". Even if "pitch" is 0 itself, it may still be effectively different due to the different alignment value. You'll probably want to first calculate the effective current and new pitch, and then compare those.
Does SetSurfaceDesc() work with mip-mapped surfaces as well? Otherwise we may have to explicitly disallow them there. Likewise for surfaces created with DDSD_LPSURFACE set.
On 5/8/20 20:40, Henri Verbeet wrote:
On Thu, 7 May 2020 at 13:54, Paul Gofman pgofman@codeweavers.com wrote:
- 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);
The pitch handling doesn't seem quite right. I.e., if texture->row_pitch is currently 0 (default), it effectively has the value calculated by wined3d_format_calculate_pitch() with the default alignment. That's potentially different from "pitch". Even if "pitch" is 0 itself, it may still be effectively different due to the different alignment value. You'll probably want to first calculate the effective current and new pitch, and then compare those.
Yes, sure.
Does SetSurfaceDesc() work with mip-mapped surfaces as well? Otherwise we may have to explicitly disallow them there. Likewise for surfaces created with DDSD_LPSURFACE set.
I tried to create a mipmapped surface with DDSD_LPSURFACE on Windows but failed to get a working flags combination for that. The main constraint is that mipmap should be texture which is supposed to be in video memory which does not allow DDSD_LPSURFACE. So unless I missed something there it does not look possible to create a DDSD_LPSURFACE mimapped texture on hardware device. Regarding SetSurfaceDesc(), I will test that with mipmaps, looks like there are no tests for that in test_set_surface_desc().
On Fri, 8 May 2020 at 22:26, Paul Gofman pgofman@codeweavers.com wrote:
I tried to create a mipmapped surface with DDSD_LPSURFACE on Windows but failed to get a working flags combination for that. The main constraint is that mipmap should be texture which is supposed to be in video memory which does not allow DDSD_LPSURFACE. So unless I missed something there it does not look possible to create a DDSD_LPSURFACE mimapped texture on hardware device.
Right, that would prevent this from being an issue.