Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2: - check for success before uploading.
dlls/wined3d/surface.c | 82 +++++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 21 deletions(-)
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 6c8d9eaf1c..9acfeea57c 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1653,6 +1653,7 @@ static HRESULT surface_cpu_blt(struct wined3d_texture *dst_texture, unsigned int unsigned int texture_level; HRESULT hr = WINED3D_OK; BOOL same_sub_resource; + BOOL upload = FALSE; DWORD map_binding; const BYTE *sbase; const BYTE *sbuf; @@ -1673,6 +1674,11 @@ static HRESULT surface_cpu_blt(struct wined3d_texture *dst_texture, unsigned int if (wined3d_format_is_typeless(dst_format) && dst_format->id == src_format->typeless_id) dst_format = src_format;
+ src_height = src_box->bottom - src_box->top; + src_width = src_box->right - src_box->left; + dst_height = dst_box->bottom - dst_box->top; + dst_width = dst_box->right - dst_box->left; + dst_range.offset = 0; dst_range.size = dst_texture->sub_resources[dst_sub_resource_idx].size; if (src_texture == dst_texture && src_sub_resource_idx == dst_sub_resource_idx) @@ -1694,6 +1700,15 @@ static HRESULT surface_cpu_blt(struct wined3d_texture *dst_texture, unsigned int else { same_sub_resource = FALSE; + upload = dst_format->flags[dst_texture->resource.gl_type] & WINED3DFMT_FLAG_BLOCKS + && (dst_width != src_width || dst_height != src_height); + + if (upload) + { + dst_format = src_format->flags[dst_texture->resource.gl_type] & WINED3DFMT_FLAG_BLOCKS + ? wined3d_get_format(device->adapter, WINED3DFMT_B8G8R8A8_UNORM, 0) : src_format; + } + if (!(flags & WINED3D_BLT_RAW) && dst_format->id != src_format->id) { if (!(converted_texture = surface_convert_format(src_texture, src_sub_resource_idx, dst_format))) @@ -1717,25 +1732,31 @@ static HRESULT surface_cpu_blt(struct wined3d_texture *dst_texture, unsigned int src_map.data = wined3d_context_map_bo_address(context, &src_data, src_texture->sub_resources[src_sub_resource_idx].size, 0, WINED3D_MAP_READ);
- map_binding = dst_texture->resource.map_binding; - texture_level = dst_sub_resource_idx % dst_texture->level_count; - if (!wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, map_binding)) - ERR("Failed to load the destination sub-resource into %s.\n", wined3d_debug_location(map_binding)); - wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~map_binding); - wined3d_texture_get_pitch(dst_texture, texture_level, &dst_map.row_pitch, &dst_map.slice_pitch); - wined3d_texture_get_memory(dst_texture, dst_sub_resource_idx, &dst_data, map_binding); - dst_map.data = wined3d_context_map_bo_address(context, &dst_data, - dst_texture->sub_resources[dst_sub_resource_idx].size, 0, WINED3D_MAP_WRITE); + if (upload) + { + wined3d_format_calculate_pitch(dst_format, 1, dst_box->right, dst_box->bottom, + &dst_map.row_pitch, &dst_map.slice_pitch); + dst_map.data = heap_alloc(dst_map.slice_pitch); + } + else + { + map_binding = dst_texture->resource.map_binding; + texture_level = dst_sub_resource_idx % dst_texture->level_count; + if (!wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, map_binding)) + ERR("Failed to load the destination sub-resource into %s.\n", wined3d_debug_location(map_binding)); + + wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~map_binding); + wined3d_texture_get_pitch(dst_texture, texture_level, &dst_map.row_pitch, &dst_map.slice_pitch); + wined3d_texture_get_memory(dst_texture, dst_sub_resource_idx, &dst_data, map_binding); + dst_map.data = wined3d_context_map_bo_address(context, &dst_data, + dst_texture->sub_resources[dst_sub_resource_idx].size, 0, WINED3D_MAP_WRITE); + } } src_fmt_flags = src_format->flags[src_texture->resource.gl_type]; dst_fmt_flags = dst_format->flags[dst_texture->resource.gl_type]; flags &= ~WINED3D_BLT_RAW;
bpp = dst_format->byte_count; - src_height = src_box->bottom - src_box->top; - src_width = src_box->right - src_box->left; - dst_height = dst_box->bottom - dst_box->top; - dst_width = dst_box->right - dst_box->left; row_byte_count = dst_width * bpp;
sbase = (BYTE *)src_map.data @@ -1756,13 +1777,6 @@ static HRESULT surface_cpu_blt(struct wined3d_texture *dst_texture, unsigned int goto release; }
- if (src_height != dst_height || src_width != dst_width) - { - WARN("Stretching not supported on compressed surfaces.\n"); - hr = WINED3DERR_INVALIDCALL; - goto release; - } - hr = surface_cpu_blt_compressed(sbase, dbuf, src_map.row_pitch, dst_map.row_pitch, dst_width, dst_height, src_format, flags, fx); @@ -2103,7 +2117,33 @@ error: FIXME(" Unsupported flags %#x.\n", flags);
release: - wined3d_context_unmap_bo_address(context, &dst_data, 0, 1, &dst_range); + if (upload && hr == WINED3D_OK) + { + struct wined3d_bo_address data; + + data.buffer_object = 0; + data.addr = dst_map.data; + + texture_level = dst_sub_resource_idx % dst_texture->level_count; + + wined3d_texture_prepare_location(dst_texture, texture_level, context, WINED3D_LOCATION_TEXTURE_RGB); + dst_texture->texture_ops->texture_upload_data(context, wined3d_const_bo_address(&data), dst_format, + dst_box, dst_map.row_pitch, dst_map.slice_pitch, dst_texture, texture_level, + WINED3D_LOCATION_TEXTURE_RGB, dst_box->left, dst_box->top, 0); + + wined3d_texture_validate_location(dst_texture, texture_level, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_texture_invalidate_location(dst_texture, texture_level, ~WINED3D_LOCATION_TEXTURE_RGB); + } + + if (upload) + { + heap_free(dst_map.data); + } + else + { + wined3d_context_unmap_bo_address(context, &dst_data, 0, 1, &dst_range); + } + if (!same_sub_resource) wined3d_context_unmap_bo_address(context, &src_data, 0, 0, NULL); if (SUCCEEDED(hr) && dst_texture->swapchain && dst_texture->swapchain->front_buffer == dst_texture)
Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2: - no changes.
dlls/ddraw/tests/ddraw7.c | 220 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+)
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index c3d575d31a..96a895630d 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -16901,6 +16901,225 @@ static void test_surface_format_conversion_alpha(void) DestroyWindow(window); }
+static void test_compressed_surface_stretch(void) +{ + static const struct + { + unsigned int src_width, src_height; + unsigned int dst_width, dst_height; + unsigned int src_x, src_y; + unsigned int dst_x, dst_y; + BOOL todo_src, todo_dst; + } + test_sizes[] = + { + {4, 4, 8, 8}, + {8, 8, 4, 4}, + {4, 4, 2, 2, 0, 0, 0, 0, FALSE, TRUE}, + {4, 4, 6, 6, 0, 0, 0, 0, FALSE, TRUE}, + {4, 4, 8, 8, 2, 2, 2, 2, TRUE, TRUE}, + }; + + static const struct + { + DWORD src_caps, dst_caps; + } + test_caps[] = + { +#if 0 + /* Broken on Windows. */ + {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY}, +#endif + {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY}, + {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY}, + {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY}, + }; + + static struct + { + DDPIXELFORMAT fmt; + const char *name; + DWORD support_flag; + } + test_formats[] = + { + { + { + sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0, + {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000} + }, + "R5G5B5A1", + }, + { + { + sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'), + {0}, {0}, {0}, {0}, {0} + }, + "DXT1", SUPPORT_DXT1, + }, + { + { + sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '3'), + {0}, {0}, {0}, {0}, {0} + }, + "DXT3", SUPPORT_DXT3, + }, + }; + + unsigned int i, j, k, l, x, y, pitch; + DDSURFACEDESC2 rb_surface_desc, src_surface_desc, dst_surface_desc, lock; + IDirectDrawSurface7 *src_surf, *dst_surf, *rb_surf; + IDirect3DDevice7 *device; + RECT src_rect, dst_rect; + DWORD supported_fmts; + unsigned short *data; + IDirectDraw7 *ddraw; + ULONG refcount; + HWND window; + BOOL passed; + DDBLTFX fx; + HRESULT hr; + + window = create_window(); + if (!(device = create_device(window, DDSCL_NORMAL))) + { + skip("Failed to create a 3D device, skipping test.\n"); + DestroyWindow(window); + return; + } + + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb, + &supported_fmts); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + memset(&src_surface_desc, 0, sizeof(src_surface_desc)); + src_surface_desc.dwSize = sizeof(src_surface_desc); + src_surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + dst_surface_desc = src_surface_desc; + + memset(&rb_surface_desc, 0, sizeof(rb_surface_desc)); + rb_surface_desc.dwSize = sizeof(rb_surface_desc); + rb_surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + U4(rb_surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(rb_surface_desc).ddpfPixelFormat); + U4(rb_surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; + U1(U4(rb_surface_desc).ddpfPixelFormat).dwRGBBitCount = 16; + U2(U4(rb_surface_desc).ddpfPixelFormat).dwRBitMask = 0x00007c00; + U3(U4(rb_surface_desc).ddpfPixelFormat).dwGBitMask = 0x000003e0; + U4(U4(rb_surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000001f; + U5(U4(rb_surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00008000; + rb_surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY; + + memset(&fx, 0, sizeof(fx)); + fx.dwSize = sizeof(fx); + + for (i = 0; i < ARRAY_SIZE(test_caps); ++i) + { + src_surface_desc.ddsCaps.dwCaps = test_caps[i].src_caps; + dst_surface_desc.ddsCaps.dwCaps = test_caps[i].dst_caps; + + for (j = 0; j < ARRAY_SIZE(test_sizes); ++j) + { + SetRect(&src_rect, test_sizes[j].src_x, test_sizes[j].src_y, + test_sizes[j].src_width, test_sizes[j].src_height); + SetRect(&dst_rect, test_sizes[j].dst_x, test_sizes[j].dst_y, + test_sizes[j].dst_width, test_sizes[j].dst_height); + + src_surface_desc.dwWidth = test_sizes[j].src_width; + src_surface_desc.dwHeight = test_sizes[j].src_height; + + dst_surface_desc.dwWidth = (test_sizes[j].dst_width + 3) & ~3; + dst_surface_desc.dwHeight = (test_sizes[j].dst_height + 3) & ~3; + + rb_surface_desc.dwWidth = max(src_surface_desc.dwWidth, dst_surface_desc.dwWidth); + rb_surface_desc.dwHeight = max(src_surface_desc.dwHeight, dst_surface_desc.dwHeight); + + hr = IDirectDraw7_CreateSurface(ddraw, &rb_surface_desc, &rb_surf, NULL); + ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", i, j, hr); + + for (k = 0; k < ARRAY_SIZE(test_formats); ++k) + { + U4(src_surface_desc).ddpfPixelFormat = test_formats[k].fmt; + hr = IDirectDraw7_CreateSurface(ddraw, &src_surface_desc, &src_surf, NULL); + ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr); + + U5(fx).dwFillColor = 0x801f; + hr = IDirectDrawSurface7_Blt(rb_surf, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); + ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr); + + hr = IDirectDrawSurface7_Blt(src_surf, &src_rect, rb_surf, &src_rect, DDBLT_WAIT, NULL); + + todo_wine_if(test_formats[k].fmt.dwFlags == DDPF_FOURCC && test_sizes[j].todo_src) + ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr); + if (FAILED(hr)) + { + IDirectDrawSurface7_Release(src_surf); + continue; + } + + for (l = 0; l < ARRAY_SIZE(test_formats); ++l) + { + if (~supported_fmts & test_formats[l].support_flag) + { + skip("%s format is not supported, skipping test %u.\n", test_formats[l].name, i); + continue; + } + + U4(dst_surface_desc).ddpfPixelFormat = test_formats[l].fmt; + + hr = IDirectDraw7_CreateSurface(ddraw, &dst_surface_desc, &dst_surf, NULL); + ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr); + + hr = IDirectDrawSurface7_Blt(dst_surf, &dst_rect, src_surf, &src_rect, DDBLT_WAIT, NULL); + todo_wine_if(test_formats[l].fmt.dwFlags == DDPF_FOURCC && test_sizes[j].todo_dst) + ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr); + if (FAILED(hr)) + { + IDirectDrawSurface7_Release(dst_surf); + continue; + } + + U5(fx).dwFillColor = 0xffffffff; + hr = IDirectDrawSurface7_Blt(rb_surf, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); + ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr); + + hr = IDirectDrawSurface7_Blt(rb_surf, &dst_rect, dst_surf, &dst_rect, DDBLT_WAIT, NULL); + ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr); + hr = IDirectDrawSurface7_Lock(rb_surf, NULL, &lock, 0, NULL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + pitch = U1(lock).lPitch; + + passed = TRUE; + for (y = dst_rect.top; y < dst_rect.bottom && passed; ++y) + { + data = (unsigned short *)((BYTE *)lock.lpSurface + y * pitch); + + for (x = dst_rect.left; x < dst_rect.right && passed; ++x) + { + passed = data[x] == 0x801f; + ok(passed, "Test (%u, %u, %u, %u), x %u, y %u, " + "got unexpected colour 0x%04x.\n", i, j, k, l, x, y, data[x]); + } + } + hr = IDirectDrawSurface7_Unlock(rb_surf, NULL); + IDirectDrawSurface7_Release(dst_surf); + } + IDirectDrawSurface7_Release(src_surf); + } + IDirectDrawSurface7_Release(rb_surf); + } + } + + IDirect3DDevice7_Release(device); + refcount = IDirectDraw7_Release(ddraw); + ok(!refcount, "%u references left.\n", refcount); + DestroyWindow(window); +} + START_TEST(ddraw7) { DDDEVICEIDENTIFIER2 identifier; @@ -17050,4 +17269,5 @@ START_TEST(ddraw7) test_caps(); test_d32_support(); test_surface_format_conversion_alpha(); + test_compressed_surface_stretch(); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=61205
Your paranoid android.
=== w8adm (32 bit report) ===
ddraw: ddraw7.c:3140: Test failed: Got unexpected hr 0x887601c2.
=== w1064v1809 (32 bit report) ===
ddraw: 1940:ddraw7: unhandled exception c0000005 at 738540F8
=== w1064v1809_2scr (32 bit report) ===
ddraw: 1ad4:ddraw7: unhandled exception c0000005 at 74CB40F8
=== w1064v1809_ar (32 bit report) ===
ddraw: 198c:ddraw7: unhandled exception c0000005 at 726C40F8
=== w1064v1809_he (32 bit report) ===
ddraw: 1ba0:ddraw7: unhandled exception c0000005 at 737C40F8
=== w1064v1809_ja (32 bit report) ===
ddraw: 1934:ddraw7: unhandled exception c0000005 at 709140F8
=== w1064v1809_zh_CN (32 bit report) ===
ddraw: 1b7c:ddraw7: unhandled exception c0000005 at 734240F8
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com