Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/wined3d/glsl_shader.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 73904ca728..05a45a046a 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -13590,14 +13590,20 @@ static BOOL glsl_blitter_supported(enum wined3d_blit_op blit_op, const struct wi return FALSE; }
+ if (!(dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU)) + { + TRACE("Destination resource does not have GPU access.\n"); + return FALSE; + } + /* We don't necessarily want to blit from resources without * WINED3D_RESOURCE_ACCESS_GPU, but that may be the only way to decompress * compressed textures. */ decompress = (src_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED) && !(dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED); - if (!decompress && !(src_resource->access & dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU)) + if (!decompress && !(src_resource->access & WINED3D_RESOURCE_ACCESS_GPU)) { - TRACE("Source or destination resource does not have GPU access.\n"); + TRACE("Source resource does not have GPU access.\n"); return FALSE; }
The motivation under this is not just supporting conversion between compressed formats. Currently fallback CPU blitter cannot convert from DXTn formats at all, this patch allows for that if software decompression function is available.
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/ddraw/tests/ddraw7.c | 2 +- dlls/wined3d/surface.c | 3 ++- dlls/wined3d/texture.c | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 13ddf623ee..1592d2e081 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -16626,7 +16626,7 @@ static void test_surface_format_conversion_alpha(void) {FMT_RGBX, rgbx_data, FMT_DXT2, dxt2_data, TRUE}, {FMT_RGBA, rgba_data, FMT_DXT3, dxt2_data}, {FMT_RGBX, rgbx_data, FMT_DXT3, dxt2_data, TRUE}, - {FMT_DXT1, dxt1_data, FMT_DXT2, dxt2_data, TRUE}, + {FMT_DXT1, dxt1_data, FMT_DXT2, dxt2_data}, {FMT_DXT1, dxt1_data, FMT_RGBA, rgba_data}, {FMT_DXT1, dxt1_data, FMT_RGBX, rgba_data}, {FMT_DXT3, dxt2_data, FMT_RGBA, rgba_data}, diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 4861bc0888..6c8d9eaf1c 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -620,7 +620,8 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr if (!(conv = find_converter(src_format->id, dst_format->id)) && (!device->d3d_initialized || !is_identity_fixup(src_format->color_fixup) || src_format->conv_byte_count || !is_identity_fixup(dst_format->color_fixup) || dst_format->conv_byte_count - || (src_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED))) + || ((src_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED) + && !src_format->decompress))) { FIXME("Cannot find a conversion function from format %s to %s.\n", debug_d3dformat(src_format->id), debug_d3dformat(dst_format->id)); diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 17b71c5738..8d3c25cf15 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -2043,7 +2043,9 @@ static void wined3d_texture_gl_upload_data(struct wined3d_context *context, bo.addr += src_box->left * src_format->byte_count; }
- decompress = dst_texture->resource.format_flags & WINED3DFMT_FLAG_DECOMPRESS; + decompress = (dst_texture->resource.format_flags & WINED3DFMT_FLAG_DECOMPRESS) + || (src_format->decompress && src_format->id != dst_texture->resource.format->id); + if (src_format->upload || decompress) { const struct wined3d_format *compressed_format = src_format;
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=59648
Your paranoid android.
=== w2008s64 (task log) ===
Task errors: The previous 1 run(s) terminated abnormally
=== w8adm (32 bit report) ===
ddraw: ddraw7.c:3036: Test failed: Failed to create surface, hr 0x887601c2. 0cf8:ddraw7: unhandled exception c0000005 at 00510105
=== w1064v1809 (32 bit report) ===
ddraw: 1964:ddraw7: unhandled exception c0000005 at 734B40F8
=== w1064v1809_2scr (32 bit report) ===
ddraw: 1af4:ddraw7: unhandled exception c0000005 at 749D40F8
=== w1064v1809_ar (32 bit report) ===
ddraw: 1bf4:ddraw7: unhandled exception c0000005 at 72CE40F8
=== w1064v1809_he (32 bit report) ===
ddraw: 1bc0:ddraw7: unhandled exception c0000005 at 731740F8
=== w1064v1809_ja (32 bit report) ===
ddraw: 1b0c:ddraw7: unhandled exception c0000005 at 71D640F8
=== w1064v1809_zh_CN (32 bit report) ===
ddraw: 19d4:ddraw7: unhandled exception c0000005 at 734440F8
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=35194 Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/ddraw/tests/ddraw7.c | 6 +-- dlls/wined3d/surface.c | 87 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 4 deletions(-)
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 1592d2e081..7f2c3e9751 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -16621,11 +16621,11 @@ static void test_surface_format_conversion_alpha(void) {FMT_R5G5B5X1, r5g5b5x1_data, FMT_R5G5B5A1, r5g5b5x1_data, TRUE}, {FMT_R5G5B5A1, r5g5b5a1_data, FMT_R5G6B5, r5g6b5_data}, {FMT_RGBA, rgba_data, FMT_DXT1, dxt1_data}, - {FMT_RGBX, rgbx_data, FMT_DXT1, dxt1_data, TRUE}, + {FMT_RGBX, rgbx_data, FMT_DXT1, dxt1_data}, {FMT_RGBA, rgba_data, FMT_DXT2, dxt2_data}, - {FMT_RGBX, rgbx_data, FMT_DXT2, dxt2_data, TRUE}, + {FMT_RGBX, rgbx_data, FMT_DXT2, dxt2_data}, {FMT_RGBA, rgba_data, FMT_DXT3, dxt2_data}, - {FMT_RGBX, rgbx_data, FMT_DXT3, dxt2_data, TRUE}, + {FMT_RGBX, rgbx_data, FMT_DXT3, dxt2_data}, {FMT_DXT1, dxt1_data, FMT_DXT2, dxt2_data}, {FMT_DXT1, dxt1_data, FMT_RGBA, rgba_data}, {FMT_DXT1, dxt1_data, FMT_RGBX, rgba_data}, diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 6c8d9eaf1c..a1dcc1d4f3 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -603,6 +603,83 @@ static inline const struct d3dfmt_converter_desc *find_converter(enum wined3d_fo return NULL; }
+static const struct d3dfmt_alpha_fixup +{ + enum wined3d_format_id format_id; + unsigned int alpha_mask; + unsigned int byte_count; +} +formats_src_alpha_fixup[] = +{ + {WINED3DFMT_B8G8R8X8_UNORM, 0xff000000, 4}, + {WINED3DFMT_B5G5R5X1_UNORM, 0x00008000, 2}, + {WINED3DFMT_B4G4R4X4_UNORM, 0x0000f000, 2}, +}; + +static void wined3d_fixup_alpha(struct wined3d_context *context, const struct wined3d_format *src_format, + const struct wined3d_format *dst_format, struct wined3d_bo_address *src_data, + unsigned int row_pitch, unsigned int width, unsigned int height, + struct wined3d_bo_address *conv_data) +{ + const struct d3dfmt_alpha_fixup *alpha_fixup = NULL; + unsigned int i, y; + BYTE *src_addr; + + memset(conv_data, 0, sizeof(*conv_data)); + + if (!(dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED) + && !dst_format->alpha_size) + return; + + for (i = 0; i < ARRAY_SIZE(formats_src_alpha_fixup); ++i) + if (formats_src_alpha_fixup[i].format_id == src_format->id) + { + alpha_fixup = &formats_src_alpha_fixup[i]; + break; + } + + if (!alpha_fixup) + return; + + if (!(conv_data->addr = heap_alloc(height * row_pitch))) + { + ERR("Failed to allocate memory.\n"); + return; + } + + src_addr = wined3d_context_map_bo_address(context, src_data, height * row_pitch, 0, WINED3D_MAP_READ); + + for (y = 0; y < height; ++y) + { + switch(alpha_fixup->byte_count) + { + case 2: + { + unsigned short *dst = (unsigned short *)(conv_data->addr + y * row_pitch); + unsigned short *src = (unsigned short *)(src_addr + y * row_pitch); + + for (i = 0; i < width; ++i) + dst[i] = src[i] | alpha_fixup->alpha_mask; + + break; + } + case 4: + { + unsigned int *dst = (unsigned int *)(conv_data->addr + y * row_pitch); + unsigned int *src = (unsigned int *)(src_addr + y * row_pitch); + + for (i = 0; i < width; ++i) + dst[i] = src[i] | alpha_fixup->alpha_mask; + + break; + } + default: + ERR("Unsupported byte count %u.\n", alpha_fixup->byte_count); + } + } + wined3d_context_unmap_bo_address(context, src_data, 0, 0, NULL); +} + static struct wined3d_texture *surface_convert_format(struct wined3d_texture *src_texture, unsigned int sub_resource_idx, const struct wined3d_format *dst_format) { @@ -685,14 +762,22 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr else { struct wined3d_box src_box = {0, 0, desc.width, desc.height, 0, 1}; + struct wined3d_bo_address conv_data;
TRACE("Using upload conversion.\n");
wined3d_texture_prepare_location(dst_texture, 0, context, WINED3D_LOCATION_TEXTURE_RGB); - dst_texture->texture_ops->texture_upload_data(context, wined3d_const_bo_address(&src_data), + + wined3d_fixup_alpha(context, src_format, dst_format, &src_data, src_row_pitch, + desc.width, desc.height, &conv_data); + + dst_texture->texture_ops->texture_upload_data(context, + wined3d_const_bo_address(conv_data.addr ? &conv_data : &src_data), src_format, &src_box, src_row_pitch, src_slice_pitch, dst_texture, 0, WINED3D_LOCATION_TEXTURE_RGB, 0, 0, 0);
+ heap_free(conv_data.addr); + wined3d_texture_validate_location(dst_texture, 0, WINED3D_LOCATION_TEXTURE_RGB); wined3d_texture_invalidate_location(dst_texture, 0, ~WINED3D_LOCATION_TEXTURE_RGB); }
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=59649
Your paranoid android.
=== w1064v1809 (32 bit report) ===
ddraw: 19a4:ddraw7: unhandled exception c0000005 at 728340F8
=== w1064v1809_2scr (32 bit report) ===
ddraw: 1bc8:ddraw7: unhandled exception c0000005 at 735140F8
=== w1064v1809_ar (32 bit report) ===
ddraw: 19d8:ddraw7: unhandled exception c0000005 at 72CE40F8
=== w1064v1809_he (32 bit report) ===
ddraw: 19bc:ddraw7: unhandled exception c0000005 at 731C40F8
=== w1064v1809_ja (32 bit report) ===
ddraw: 1998:ddraw7: unhandled exception c0000005 at 71D840F8
=== w1064v1809_zh_CN (32 bit report) ===
ddraw: 136c:ddraw7: unhandled exception c0000005 at 734140F8
On Fri, 8 Nov 2019 at 15:28, Paul Gofman gofmanp@gmail.com wrote:
@@ -685,14 +762,22 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr else { struct wined3d_box src_box = {0, 0, desc.width, desc.height, 0, 1};
struct wined3d_bo_address conv_data; TRACE("Using upload conversion.\n"); wined3d_texture_prepare_location(dst_texture, 0, context, WINED3D_LOCATION_TEXTURE_RGB);
dst_texture->texture_ops->texture_upload_data(context, wined3d_const_bo_address(&src_data),
wined3d_fixup_alpha(context, src_format, dst_format, &src_data, src_row_pitch,
desc.width, desc.height, &conv_data);
Although X-channel data is undefined, it seems undesirable to modify the source data. Wouldn't it be better to fixup the destination data instead?
On 11/11/19 19:07, Henri Verbeet wrote:
On Fri, 8 Nov 2019 at 15:28, Paul Gofman gofmanp@gmail.com wrote:
@@ -685,14 +762,22 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr else { struct wined3d_box src_box = {0, 0, desc.width, desc.height, 0, 1};
struct wined3d_bo_address conv_data; TRACE("Using upload conversion.\n"); wined3d_texture_prepare_location(dst_texture, 0, context, WINED3D_LOCATION_TEXTURE_RGB);
dst_texture->texture_ops->texture_upload_data(context, wined3d_const_bo_address(&src_data),
wined3d_fixup_alpha(context, src_format, dst_format, &src_data, src_row_pitch,
desc.width, desc.height, &conv_data);
Although X-channel data is undefined, it seems undesirable to modify the source data. Wouldn't it be better to fixup the destination data instead?
But I thought I don't modify source data: wined3d_fixup_alpha() allocates temporary buffer and maps source data as read only. Or am I missing your point?
On Mon, 11 Nov 2019 at 19:43, Paul Gofman gofmanp@gmail.com wrote:
On 11/11/19 19:07, Henri Verbeet wrote:
On Fri, 8 Nov 2019 at 15:28, Paul Gofman gofmanp@gmail.com wrote:
@@ -685,14 +762,22 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr else { struct wined3d_box src_box = {0, 0, desc.width, desc.height, 0, 1};
struct wined3d_bo_address conv_data; TRACE("Using upload conversion.\n"); wined3d_texture_prepare_location(dst_texture, 0, context, WINED3D_LOCATION_TEXTURE_RGB);
dst_texture->texture_ops->texture_upload_data(context, wined3d_const_bo_address(&src_data),
wined3d_fixup_alpha(context, src_format, dst_format, &src_data, src_row_pitch,
desc.width, desc.height, &conv_data);
Although X-channel data is undefined, it seems undesirable to modify the source data. Wouldn't it be better to fixup the destination data instead?
But I thought I don't modify source data: wined3d_fixup_alpha() allocates temporary buffer and maps source data as read only. Or am I missing your point?
No, you're right, my bad.
On Mon, 11 Nov 2019 at 20:03, Henri Verbeet hverbeet@gmail.com wrote:
On Mon, 11 Nov 2019 at 19:43, Paul Gofman gofmanp@gmail.com wrote:
On 11/11/19 19:07, Henri Verbeet wrote:
On Fri, 8 Nov 2019 at 15:28, Paul Gofman gofmanp@gmail.com wrote:
@@ -685,14 +762,22 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr else { struct wined3d_box src_box = {0, 0, desc.width, desc.height, 0, 1};
struct wined3d_bo_address conv_data; TRACE("Using upload conversion.\n"); wined3d_texture_prepare_location(dst_texture, 0, context, WINED3D_LOCATION_TEXTURE_RGB);
dst_texture->texture_ops->texture_upload_data(context, wined3d_const_bo_address(&src_data),
wined3d_fixup_alpha(context, src_format, dst_format, &src_data, src_row_pitch,
desc.width, desc.height, &conv_data);
Although X-channel data is undefined, it seems undesirable to modify the source data. Wouldn't it be better to fixup the destination data instead?
But I thought I don't modify source data: wined3d_fixup_alpha() allocates temporary buffer and maps source data as read only. Or am I missing your point?
No, you're right, my bad.
Although looking a bit closer at the patch, it still seems a relatively fragile way to fix the issue. It works because texture_upload_data() uses e.g. GL_BGRA/GL_UNSIGNED_INT_8_8_8_8_REV for uploading WINED3DFMT_B8G8R8X8_UNORM data, but the caller isn't supposed to care about that, and a different backend (e.g. Vulkan) could do uploads in a different way.
On 11/11/19 20:12, Henri Verbeet wrote:
On Mon, 11 Nov 2019 at 20:03, Henri Verbeet hverbeet@gmail.com wrote:
On Mon, 11 Nov 2019 at 19:43, Paul Gofman gofmanp@gmail.com wrote:
On 11/11/19 19:07, Henri Verbeet wrote:
On Fri, 8 Nov 2019 at 15:28, Paul Gofman gofmanp@gmail.com wrote:
@@ -685,14 +762,22 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_texture *sr else { struct wined3d_box src_box = {0, 0, desc.width, desc.height, 0, 1};
struct wined3d_bo_address conv_data; TRACE("Using upload conversion.\n"); wined3d_texture_prepare_location(dst_texture, 0, context, WINED3D_LOCATION_TEXTURE_RGB);
dst_texture->texture_ops->texture_upload_data(context, wined3d_const_bo_address(&src_data),
wined3d_fixup_alpha(context, src_format, dst_format, &src_data, src_row_pitch,
desc.width, desc.height, &conv_data);
Although X-channel data is undefined, it seems undesirable to modify the source data. Wouldn't it be better to fixup the destination data instead?
But I thought I don't modify source data: wined3d_fixup_alpha() allocates temporary buffer and maps source data as read only. Or am I missing your point?
No, you're right, my bad.
Although looking a bit closer at the patch, it still seems a relatively fragile way to fix the issue. It works because texture_upload_data() uses e.g. GL_BGRA/GL_UNSIGNED_INT_8_8_8_8_REV for uploading WINED3DFMT_B8G8R8X8_UNORM data, but the caller isn't supposed to care about that, and a different backend (e.g. Vulkan) could do uploads in a different way.
I think the only reason why this type of fixup is needed is because we have the underlying format for _B8G8R8X8_UNORM which has an explicit alpha. So I suppose if WINED3DFMT_B8G8R8X8_UNORM gets underlying format without alpha, this conversion should not break but rather become redundant, as probably upload conversion should put alpha of 1.0 in this case. Should I maybe move this alpha fixup to wined3d_texture_gl_upload_data()?
On Mon, 11 Nov 2019 at 21:07, Paul Gofman gofmanp@gmail.com wrote:
On 11/11/19 20:12, Henri Verbeet wrote:
Although looking a bit closer at the patch, it still seems a relatively fragile way to fix the issue. It works because texture_upload_data() uses e.g. GL_BGRA/GL_UNSIGNED_INT_8_8_8_8_REV for uploading WINED3DFMT_B8G8R8X8_UNORM data, but the caller isn't supposed to care about that, and a different backend (e.g. Vulkan) could do uploads in a different way.
I think the only reason why this type of fixup is needed is because we have the underlying format for _B8G8R8X8_UNORM which has an explicit alpha. So I suppose if WINED3DFMT_B8G8R8X8_UNORM gets underlying format without alpha, this conversion should not break but rather become redundant, as probably upload conversion should put alpha of 1.0 in this case. Should I maybe move this alpha fixup to wined3d_texture_gl_upload_data()?
It seems more appropriate to do it in wined3d_texture_gl_upload_data(), yeah. Ideally, it would also check for the actual condition we care about. I.e., uploading to a GL internal format with alpha channel, from a D3D format without alpha, but a GL upload format with alpha. We don't track that information about the OpenGL formats though, and it's probably not worth adding just for this, so perhaps checking for uploads from a D3D format without alpha to a D3D format with alpha is close enough.
One more observation is that e.g. WINED3DFMT_B8G8R8X8_UNORM has an equivalent format with alpha, WINED3DFMT_B8G8R8A8_UNORM, which could be used for looking up the masks and byte counts.
On 11/11/19 21:09, Henri Verbeet wrote:
On Mon, 11 Nov 2019 at 21:07, Paul Gofman gofmanp@gmail.com wrote:
On 11/11/19 20:12, Henri Verbeet wrote:
Although looking a bit closer at the patch, it still seems a relatively fragile way to fix the issue. It works because texture_upload_data() uses e.g. GL_BGRA/GL_UNSIGNED_INT_8_8_8_8_REV for uploading WINED3DFMT_B8G8R8X8_UNORM data, but the caller isn't supposed to care about that, and a different backend (e.g. Vulkan) could do uploads in a different way.
I think the only reason why this type of fixup is needed is because we have the underlying format for _B8G8R8X8_UNORM which has an explicit alpha. So I suppose if WINED3DFMT_B8G8R8X8_UNORM gets underlying format without alpha, this conversion should not break but rather become redundant, as probably upload conversion should put alpha of 1.0 in this case. Should I maybe move this alpha fixup to wined3d_texture_gl_upload_data()?
One more observation is that e.g. WINED3DFMT_B8G8R8X8_UNORM has an equivalent format with alpha, WINED3DFMT_B8G8R8A8_UNORM, which could be used for looking up the masks and byte counts.
But how do I link WINED3DFMT_B8G8R8X8_UNORM, WINED3DFMT_B5G5R5X1_UNORM or WINED3DFMT_B4G4R4X4_UNORM to their counterpart with alpha? Should I probably still use a table for that, just reference the format with alpha instead of directly coding size and mask?
On Mon, 11 Nov 2019 at 21:45, Paul Gofman gofmanp@gmail.com wrote:
On 11/11/19 21:09, Henri Verbeet wrote:
One more observation is that e.g. WINED3DFMT_B8G8R8X8_UNORM has an equivalent format with alpha, WINED3DFMT_B8G8R8A8_UNORM, which could be used for looking up the masks and byte counts.
But how do I link WINED3DFMT_B8G8R8X8_UNORM, WINED3DFMT_B5G5R5X1_UNORM or WINED3DFMT_B4G4R4X4_UNORM to their counterpart with alpha? Should I probably still use a table for that, just reference the format with alpha instead of directly coding size and mask?
Yeah, you'd still need the table to map between the formats.
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/ddraw/tests/ddraw7.c | 142 ++++++++++++++++++++++++-------------- 1 file changed, 89 insertions(+), 53 deletions(-)
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 7f2c3e9751..12d330c123 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -16539,6 +16539,7 @@ static void test_surface_format_conversion_alpha(void) const char *name; unsigned int block_size, x_blocks, y_blocks; DWORD support_flag; + BOOL broken_software_blit; } formats[] = { @@ -16561,7 +16562,10 @@ static void test_surface_format_conversion_alpha(void) sizeof(DDPIXELFORMAT), DDPF_RGB, 0, {16}, {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000} }, - "R5G6B5", 2, 4, 4, + "R5G6B5", 2, 4, 4, 0, TRUE, + /* Looks broken for sysmem texture convertions on Windows (at least with hardware + * device), the result is either error from _Blt() or a copy of the source data + * without any conversion. */ }, { { @@ -16600,6 +16604,18 @@ static void test_surface_format_conversion_alpha(void) }, };
+ static const struct + { + DWORD src_caps, dst_caps; + } + test_caps[] = + { + {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY}, + {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 const struct { enum test_format_id src_format; @@ -16636,11 +16652,12 @@ static void test_surface_format_conversion_alpha(void) const struct test_format *src_format, *dst_format; IDirectDrawSurface7 *src_surf, *dst_surf; DDSURFACEDESC2 surface_desc, lock; - unsigned int i, x, y, pitch; + unsigned int i, j, x, y, pitch; IDirect3DDevice7 *device; DWORD supported_fmts; IDirectDraw7 *ddraw; ULONG refcount; + BOOL is_wine; HWND window; BOOL passed; HRESULT hr; @@ -16662,12 +16679,13 @@ static void test_surface_format_conversion_alpha(void) &supported_fmts); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ is_wine = !strcmp(winetest_platform, "wine"); + memset(&surface_desc, 0, sizeof(surface_desc)); surface_desc.dwSize = sizeof(surface_desc); surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; surface_desc.dwWidth = 4; surface_desc.dwHeight = 4; - surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
for (i = 0; i < ARRAY_SIZE(tests); ++i) { @@ -16685,63 +16703,81 @@ static void test_surface_format_conversion_alpha(void) continue; }
- U4(surface_desc).ddpfPixelFormat = src_format->fmt; - hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surf, NULL); - ok(hr == DD_OK, "Test %u, got unexpected hr %#x.\n", i, hr); - - U4(surface_desc).ddpfPixelFormat = dst_format->fmt; - hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surf, NULL); - ok(hr == DD_OK, "Test %u, got unexpected hr %#x.\n", i, hr); - - memset(&lock, 0, sizeof(lock)); - lock.dwSize = sizeof(lock); - hr = IDirectDrawSurface7_Lock(src_surf, NULL, &lock, 0, NULL); - ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); - pitch = U1(lock).lPitch; - for (y = 0; y < src_format->y_blocks; ++y) - memcpy((BYTE*)lock.lpSurface + y * pitch, - (BYTE *)tests[i].src_data + y * src_format->x_blocks * src_format->block_size, - src_format->block_size * src_format->x_blocks); - hr = IDirectDrawSurface7_Unlock(src_surf, NULL); - ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + for (j = 0; j < ARRAY_SIZE(test_caps); ++j) + { + if (!is_wine && ((test_caps[j].src_caps | test_caps[j].dst_caps) & DDSCAPS_SYSTEMMEMORY) + && (src_format->broken_software_blit || dst_format->broken_software_blit)) + continue;
- hr = IDirectDrawSurface7_Blt(dst_surf, NULL, src_surf, NULL, DDBLT_WAIT, NULL); - ok(hr == DD_OK, "Test %s -> %s, got unexpected hr %#x.\n", - src_format->name, dst_format->name, hr); + U4(surface_desc).ddpfPixelFormat = src_format->fmt; + surface_desc.ddsCaps.dwCaps = test_caps[j].src_caps; + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surf, NULL); + ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", j, i, hr); + + U4(surface_desc).ddpfPixelFormat = dst_format->fmt; + surface_desc.ddsCaps.dwCaps = test_caps[j].dst_caps; + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surf, NULL); + ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", j, i, hr); + + memset(&lock, 0, sizeof(lock)); + lock.dwSize = sizeof(lock); + hr = IDirectDrawSurface7_Lock(src_surf, NULL, &lock, 0, NULL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + pitch = U1(lock).lPitch; + for (y = 0; y < src_format->y_blocks; ++y) + memcpy((BYTE*)lock.lpSurface + y * pitch, + (BYTE *)tests[i].src_data + y * src_format->x_blocks * src_format->block_size, + src_format->block_size * src_format->x_blocks); + hr = IDirectDrawSurface7_Unlock(src_surf, NULL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirectDrawSurface7_Blt(dst_surf, NULL, src_surf, NULL, DDBLT_WAIT, NULL); + if (!is_wine && FAILED(hr)) + { + /* Some software blits are rejected on Windows. */ + IDirectDrawSurface7_Release(dst_surf); + IDirectDrawSurface7_Release(src_surf); + skip("Skipping test (%u, %u), cannot blit %s -> %s, hr %#x.\n", j, i, + src_format->name, dst_format->name, hr); + continue; + } + ok(hr == DD_OK, "Test (%u, %s -> %s), got unexpected hr %#x.\n", j, + src_format->name, dst_format->name, hr);
- memset(&lock, 0, sizeof(lock)); - lock.dwSize = sizeof(lock); - hr = IDirectDrawSurface7_Lock(dst_surf, NULL, &lock, 0, NULL); - ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); - pitch = U1(lock).lPitch; + memset(&lock, 0, sizeof(lock)); + lock.dwSize = sizeof(lock); + hr = IDirectDrawSurface7_Lock(dst_surf, NULL, &lock, 0, NULL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + pitch = U1(lock).lPitch;
- for (y = 0; y < dst_format->y_blocks; ++y) - { - const void *expected_data = tests[i].expected_data; + for (y = 0; y < dst_format->y_blocks; ++y) + { + const void *expected_data = tests[i].expected_data;
- passed = !memcmp((BYTE*)lock.lpSurface + y * pitch, - (BYTE *)expected_data + y * dst_format->x_blocks * dst_format->block_size, - dst_format->block_size * dst_format->x_blocks); - todo_wine_if(tests[i].todo) - ok(passed, "Test %s -> %s, row %u, unexpected surface data.\n", - src_format->name, dst_format->name, y); + passed = !memcmp((BYTE*)lock.lpSurface + y * pitch, + (BYTE *)expected_data + y * dst_format->x_blocks * dst_format->block_size, + dst_format->block_size * dst_format->x_blocks); + todo_wine_if(tests[i].todo) + ok(passed, "Test (%u, %s -> %s), row %u, unexpected surface data.\n", j, + src_format->name, dst_format->name, y);
- if (!passed && !(!strcmp(winetest_platform, "wine") && tests[i].todo)) - { - for (x = 0; x < dst_format->x_blocks * dst_format->block_size / 4; ++x) - trace("Test %u, x %u, y %u, got 0x%08x, expected 0x%08x.\n", i, x, y, - *(unsigned int *)((BYTE *)lock.lpSurface + y * pitch + x * 4), - *(unsigned int *)((BYTE *)expected_data + y * dst_format->x_blocks - * dst_format->block_size + x * 4)); + if (!passed && !(is_wine && tests[i].todo)) + { + for (x = 0; x < dst_format->x_blocks * dst_format->block_size / 4; ++x) + trace("Test (%u, %u), x %u, y %u, got 0x%08x, expected 0x%08x.\n", j, i, x, y, + *(unsigned int *)((BYTE *)lock.lpSurface + y * pitch + x * 4), + *(unsigned int *)((BYTE *)expected_data + y * dst_format->x_blocks + * dst_format->block_size + x * 4)); + } + if (!passed) + break; } - if (!passed) - break; - } - hr = IDirectDrawSurface7_Unlock(dst_surf, NULL); - ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_Unlock(dst_surf, NULL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
- IDirectDrawSurface7_Release(dst_surf); - IDirectDrawSurface7_Release(src_surf); + IDirectDrawSurface7_Release(dst_surf); + IDirectDrawSurface7_Release(src_surf); + } }
IDirect3DDevice7_Release(device);
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=59650
Your paranoid android.
=== w1064v1809 (32 bit report) ===
ddraw: 19b0:ddraw7: unhandled exception c0000005 at 739B40F8
=== w1064v1809_2scr (32 bit report) ===
ddraw: 1b14:ddraw7: unhandled exception c0000005 at 734240F8
=== w1064v1809_ar (32 bit report) ===
ddraw: 15e0:ddraw7: unhandled exception c0000005 at 72A640F8
=== w1064v1809_he (32 bit report) ===
ddraw: 1a88:ddraw7: unhandled exception c0000005 at 737E40F8
=== w1064v1809_ja (32 bit report) ===
ddraw: 1a64:ddraw7: unhandled exception c0000005 at 71D440F8
=== w1064v1809_zh_CN (32 bit report) ===
ddraw: 1bb0:ddraw7: unhandled exception c0000005 at 734240F8
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/ddraw/tests/ddraw4.c | 312 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 312 insertions(+)
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index fdcf6dff87..bea0f66dce 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -16504,6 +16504,317 @@ static void test_d32_support(void) DestroyWindow(window); }
+static void test_surface_format_conversion_alpha(void) +{ + static const unsigned int rgba_data[4 * 4] = + { + 0xff00ff00, 0xff0000ff, 0xff0000ff, 0xff0000ff, + 0xff0000ff, 0xff00ff00, 0xff0000ff, 0xff0000ff, + 0xff00ff00, 0xff0000ff, 0xff00ff00, 0xff0000ff, + 0xff00ff00, 0xff0000ff, 0xff0000ff, 0xff00ff00, + }; + static const unsigned int rgbx_data[4 * 4] = + { + 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, + 0x000000ff, 0x0000ff00, 0x000000ff, 0x000000ff, + 0x0000ff00, 0x000000ff, 0x0000ff00, 0x000000ff, + 0x0000ff00, 0x000000ff, 0x000000ff, 0x0000ff00, + }; + static const unsigned short int r5g6b5_data[4 * 4] = + { + 0x07e0, 0x001f, 0x001f, 0x001f, + 0x001f, 0x07e0, 0x001f, 0x001f, + 0x07e0, 0x001f, 0x07e0, 0x001f, + 0x07e0, 0x001f, 0x001f, 0x07e0, + }; + static const unsigned short int r5g5b5x1_data[4 * 4] = + { + 0x03e0, 0x001f, 0x001f, 0x001f, + 0x001f, 0x03e0, 0x001f, 0x001f, + 0x03e0, 0x001f, 0x03e0, 0x001f, + 0x03e0, 0x001f, 0x001f, 0x03e0, + }; + static const unsigned short int r5g5b5a1_data[4 * 4] = + { + 0x83e0, 0x801f, 0x801f, 0x801f, + 0x801f, 0x83e0, 0x801f, 0x801f, + 0x83e0, 0x801f, 0x83e0, 0x801f, + 0x83e0, 0x801f, 0x801f, 0x83e0, + }; + static const unsigned int dxt1_data[8] = + { + 0x001f07e0, 0x14445154, + }; + static const unsigned int dxt2_data[16] = + { + 0xffffffff, 0xffffffff, 0x001f07e0, 0x14445154, + }; + + enum test_format_id + { + FMT_RGBA, + FMT_RGBX, + FMT_R5G6B5, + FMT_R5G5B5X1, + FMT_R5G5B5A1, + FMT_DXT1, + FMT_DXT2, + FMT_DXT3, + }; + + static const struct test_format + { + DDPIXELFORMAT fmt; + const char *name; + unsigned int block_size, x_blocks, y_blocks; + DWORD support_flag; + BOOL broken_software_blit; + } + formats[] = + { + { + { + sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0, + {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000} + }, + "RGBA", 4, 4, 4, + }, + { + { + sizeof(DDPIXELFORMAT), DDPF_RGB, 0, + {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000} + }, + "RGBX", 4, 4, 4, + }, + { + { + sizeof(DDPIXELFORMAT), DDPF_RGB, 0, + {16}, {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000} + }, + "R5G6B5", 2, 4, 4, 0, TRUE, + /* Looks broken for sysmem texture convertions on Windows (at least with hardware + * device), the result is either error from _Blt() or a copy of the source data + * without any conversion. */ + }, + { + { + sizeof(DDPIXELFORMAT), DDPF_RGB, 0, + {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000} + }, + "R5G5B5X1", 2, 4, 4, + }, + { + { + sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0, + {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000} + }, + "R5G5B5A1", 2, 4, 4, + }, + { + { + sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'), + {0}, {0}, {0}, {0}, {0} + }, + "DXT1", 8, 1, 1, SUPPORT_DXT1, + }, + { + { + sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '2'), + {0}, {0}, {0}, {0}, {0} + }, + "DXT2", 16, 1, 1, SUPPORT_DXT2, + }, + { + { + sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '3'), + {0}, {0}, {0}, {0}, {0} + }, + "DXT3", 16, 1, 1, SUPPORT_DXT3, + }, + }; + + static const struct + { + DWORD src_caps, dst_caps; + } + test_caps[] = + { + {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY}, + {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 const struct + { + enum test_format_id src_format; + const void *src_data; + enum test_format_id dst_format; + const void *expected_data; + BOOL todo; + } + tests[] = + { +#if 0 + /* The following 3 tests give different results on AMD and NVIDIA on Windows, disabling. */ + {FMT_RGBX, rgbx_data, FMT_RGBA, rgba_data}, + {FMT_RGBA, rgba_data, FMT_RGBX, rgbx_data}, + {FMT_R5G5B5X1, r5g5b5x1_data, FMT_RGBA, rgba_data}, +#endif + {FMT_R5G6B5, r5g6b5_data, FMT_RGBA, rgba_data}, + {FMT_R5G6B5, r5g6b5_data, FMT_R5G5B5A1, r5g5b5a1_data}, + {FMT_R5G5B5X1, r5g5b5x1_data, FMT_R5G5B5A1, r5g5b5x1_data, TRUE}, + {FMT_R5G5B5A1, r5g5b5a1_data, FMT_R5G6B5, r5g6b5_data}, + {FMT_RGBA, rgba_data, FMT_DXT1, dxt1_data}, + {FMT_RGBX, rgbx_data, FMT_DXT1, dxt1_data}, + {FMT_RGBA, rgba_data, FMT_DXT2, dxt2_data}, + {FMT_RGBX, rgbx_data, FMT_DXT2, dxt2_data}, + {FMT_RGBA, rgba_data, FMT_DXT3, dxt2_data}, + {FMT_RGBX, rgbx_data, FMT_DXT3, dxt2_data}, + {FMT_DXT1, dxt1_data, FMT_DXT2, dxt2_data}, + {FMT_DXT1, dxt1_data, FMT_RGBA, rgba_data}, + {FMT_DXT1, dxt1_data, FMT_RGBX, rgba_data}, + {FMT_DXT3, dxt2_data, FMT_RGBA, rgba_data}, + {FMT_DXT3, dxt2_data, FMT_RGBX, rgba_data}, + }; + + const struct test_format *src_format, *dst_format; + IDirectDrawSurface4 *src_surf, *dst_surf; + DDSURFACEDESC2 surface_desc, lock; + unsigned int i, j, x, y, pitch; + IDirect3DDevice3 *device; + DWORD supported_fmts; + IDirectDraw4 *ddraw; + ULONG refcount; + BOOL is_wine; + HWND window; + BOOL passed; + 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 = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirect3DDevice3_EnumTextureFormats(device, test_block_formats_creation_cb, + &supported_fmts); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + is_wine = !strcmp(winetest_platform, "wine"); + + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + surface_desc.dwWidth = 4; + surface_desc.dwHeight = 4; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + src_format = &formats[tests[i].src_format]; + dst_format = &formats[tests[i].dst_format]; + + if (~supported_fmts & dst_format->support_flag) + { + skip("%s format is not supported, skipping test %u.\n", dst_format->name, i); + continue; + } + if (~supported_fmts & src_format->support_flag) + { + skip("%s format is not supported, skipping test %u.\n", src_format->name, i); + continue; + } + + for (j = 0; j < ARRAY_SIZE(test_caps); ++j) + { + if (!is_wine && ((test_caps[j].src_caps | test_caps[j].dst_caps) & DDSCAPS_SYSTEMMEMORY) + && (src_format->broken_software_blit || dst_format->broken_software_blit)) + continue; + + U4(surface_desc).ddpfPixelFormat = src_format->fmt; + surface_desc.ddsCaps.dwCaps = test_caps[j].src_caps; + hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surf, NULL); + ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", j, i, hr); + + U4(surface_desc).ddpfPixelFormat = dst_format->fmt; + surface_desc.ddsCaps.dwCaps = test_caps[j].dst_caps; + hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surf, NULL); + ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", j, i, hr); + + memset(&lock, 0, sizeof(lock)); + lock.dwSize = sizeof(lock); + hr = IDirectDrawSurface4_Lock(src_surf, NULL, &lock, 0, NULL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + pitch = U1(lock).lPitch; + for (y = 0; y < src_format->y_blocks; ++y) + memcpy((BYTE*)lock.lpSurface + y * pitch, + (BYTE *)tests[i].src_data + y * src_format->x_blocks * src_format->block_size, + src_format->block_size * src_format->x_blocks); + hr = IDirectDrawSurface4_Unlock(src_surf, NULL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirectDrawSurface4_Blt(dst_surf, NULL, src_surf, NULL, DDBLT_WAIT, NULL); + if (!is_wine && FAILED(hr)) + { + /* Some software blits are rejected on Windows. */ + IDirectDrawSurface4_Release(dst_surf); + IDirectDrawSurface4_Release(src_surf); + skip("Skipping test (%u, %u), cannot blit %s -> %s, hr %#x.\n", j, i, + src_format->name, dst_format->name, hr); + continue; + } + ok(hr == DD_OK, "Test (%u, %s -> %s), got unexpected hr %#x.\n", j, + src_format->name, dst_format->name, hr); + + memset(&lock, 0, sizeof(lock)); + lock.dwSize = sizeof(lock); + hr = IDirectDrawSurface4_Lock(dst_surf, NULL, &lock, 0, NULL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + pitch = U1(lock).lPitch; + + for (y = 0; y < dst_format->y_blocks; ++y) + { + const void *expected_data = tests[i].expected_data; + + passed = !memcmp((BYTE*)lock.lpSurface + y * pitch, + (BYTE *)expected_data + y * dst_format->x_blocks * dst_format->block_size, + dst_format->block_size * dst_format->x_blocks); + todo_wine_if(tests[i].todo) + ok(passed, "Test (%u, %s -> %s), row %u, unexpected surface data.\n", j, + src_format->name, dst_format->name, y); + + if (!passed && !(is_wine && tests[i].todo)) + { + for (x = 0; x < dst_format->x_blocks * dst_format->block_size / 4; ++x) + trace("Test (%u, %u), x %u, y %u, got 0x%08x, expected 0x%08x.\n", j, i, x, y, + *(unsigned int *)((BYTE *)lock.lpSurface + y * pitch + x * 4), + *(unsigned int *)((BYTE *)expected_data + y * dst_format->x_blocks + * dst_format->block_size + x * 4)); + } + if (!passed) + break; + } + hr = IDirectDrawSurface4_Unlock(dst_surf, NULL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + IDirectDrawSurface4_Release(dst_surf); + IDirectDrawSurface4_Release(src_surf); + } + } + + IDirect3DDevice3_Release(device); + refcount = IDirectDraw4_Release(ddraw); + ok(!refcount, "%u references left.\n", refcount); + DestroyWindow(window); +} + START_TEST(ddraw4) { DDDEVICEIDENTIFIER identifier; @@ -16638,4 +16949,5 @@ START_TEST(ddraw4) test_clipper_refcount(); test_caps(); test_d32_support(); + test_surface_format_conversion_alpha(); }