From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/tests/d3dx10.c | 7 +- dlls/d3dx11_43/tests/d3dx11.c | 7 +- dlls/d3dx9_36/d3dx_helpers.c | 141 ++++++++++++++++++++++++++++++++++ dlls/d3dx9_36/d3dx_helpers.h | 6 ++ dlls/d3dx9_36/tests/surface.c | 2 +- dlls/d3dx9_36/tests/texture.c | 8 +- dlls/d3dx9_36/tests/volume.c | 8 +- dlls/d3dx9_36/texture.c | 6 -- 8 files changed, 166 insertions(+), 19 deletions(-)
diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 67fff3e0f6f..3ea4499f20e 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -5423,6 +5423,7 @@ static void test_image_filters(void) const void *expected_dst_data; const void *expected_dst_data_32; BOOL todo; + uint32_t max_diff; } filter_expected[4]; } tests[] = @@ -5433,7 +5434,7 @@ static void test_image_filters(void) { a8r8g8b8_16_16_point_filter_8_8 }, { a8r8g8b8_16_16_linear_filter_8_8, .todo = TRUE }, { a8r8g8b8_16_16_triangle_filter_8_8, a8r8g8b8_16_16_triangle_filter_8_8_32bit, .todo = TRUE }, - { a8r8g8b8_16_16_box_filter_8_8, .todo = TRUE }, + { a8r8g8b8_16_16_box_filter_8_8 }, }, }, { @@ -5504,7 +5505,7 @@ static void test_image_filters(void) { a8r8g8b8_8_8_8_point_filter_4_4_4 }, { a8r8g8b8_8_8_8_linear_filter_4_4_4, .todo = TRUE }, { a8r8g8b8_8_8_8_triangle_filter_4_4_4, .todo = TRUE }, - { a8r8g8b8_8_8_8_box_filter_4_4_4, .todo = TRUE }, + { a8r8g8b8_8_8_8_box_filter_4_4_4, .max_diff = 1 }, }, }, { @@ -5586,7 +5587,7 @@ static void test_image_filters(void)
get_resource_readback(resource, 0, &rb); todo_wine_if(tests[i].filter_expected[j].todo) check_test_readback(&rb, expected_dst, tests[i].dst_width, - tests[i].dst_height, tests[i].dst_depth, tests[i].format, 0); + tests[i].dst_height, tests[i].dst_depth, tests[i].format, tests[i].filter_expected[j].max_diff); release_resource_readback(&rb); ID3D10Resource_Release(resource);
diff --git a/dlls/d3dx11_43/tests/d3dx11.c b/dlls/d3dx11_43/tests/d3dx11.c index cceb08d20ba..8210329e6d5 100644 --- a/dlls/d3dx11_43/tests/d3dx11.c +++ b/dlls/d3dx11_43/tests/d3dx11.c @@ -4258,6 +4258,7 @@ static void test_image_filters(void) const void *expected_dst_data; const void *expected_dst_data_32; BOOL todo; + uint32_t max_diff; } filter_expected[4]; } tests[] = @@ -4268,7 +4269,7 @@ static void test_image_filters(void) { a8r8g8b8_16_16_point_filter_8_8 }, { a8r8g8b8_16_16_linear_filter_8_8, .todo = TRUE }, { a8r8g8b8_16_16_triangle_filter_8_8, a8r8g8b8_16_16_triangle_filter_8_8_32bit, .todo = TRUE }, - { a8r8g8b8_16_16_box_filter_8_8, .todo = TRUE }, + { a8r8g8b8_16_16_box_filter_8_8 }, }, }, { @@ -4339,7 +4340,7 @@ static void test_image_filters(void) { a8r8g8b8_8_8_8_point_filter_4_4_4 }, { a8r8g8b8_8_8_8_linear_filter_4_4_4, .todo = TRUE }, { a8r8g8b8_8_8_8_triangle_filter_4_4_4, .todo = TRUE }, - { a8r8g8b8_8_8_8_box_filter_4_4_4, .todo = TRUE }, + { a8r8g8b8_8_8_8_box_filter_4_4_4, .max_diff = 1 }, }, }, { @@ -4421,7 +4422,7 @@ static void test_image_filters(void)
get_resource_readback(resource, 0, &rb); todo_wine_if(tests[i].filter_expected[j].todo) check_test_readback(&rb, expected_dst, tests[i].dst_width, - tests[i].dst_height, tests[i].dst_depth, tests[i].format, 0); + tests[i].dst_height, tests[i].dst_depth, tests[i].format, tests[i].filter_expected[j].max_diff); release_resource_readback(&rb); ID3D11Resource_Release(resource);
diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c index 69a54ed4188..684bc50e5eb 100644 --- a/dlls/d3dx9_36/d3dx_helpers.c +++ b/dlls/d3dx9_36/d3dx_helpers.c @@ -467,6 +467,17 @@ uint32_t d3dx_get_max_mip_levels_for_size(uint32_t width, uint32_t height, uint3 return mip_levels; }
+static BOOL d3dx_size_is_half(struct volume *src, struct volume *dst) +{ + return (max(src->width / 2, 1) == dst->width) && (max(src->height / 2, 1) == dst->height) + && (max(src->depth / 2, 1) == dst->depth); +} + +static BOOL d3dx_size_is_pow2(struct volume *size) +{ + return is_pow2(size->width) && is_pow2(size->height) && is_pow2(size->depth); +} + static const char *debug_volume(const struct volume *volume) { if (!volume) @@ -2587,6 +2598,118 @@ static void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT s } }
+static void check_color_key(struct d3dx_color *color, const struct d3dx_color_key *color_key, + const struct pixel_format_desc *ck_format) +{ + struct d3dx_color tmp; + DWORD ck_pixel = 0; + unsigned int i; + + tmp = *color; + format_from_d3dx_color(ck_format, &tmp, (BYTE *)&ck_pixel); + for (i = 0; i < 4; ++i) + { + const uint8_t ck_channel = (ck_pixel >> (24 - (i * 8))) & 0xff; + + if ((ck_channel < color_key->color_key_min[i]) || (ck_channel > color_key->color_key_max[i])) + break; + } + + if (i == 4) + tmp.value.x = tmp.value.y = tmp.value.z = tmp.value.w = 0.0f; + + *color = tmp; +} + +static inline void vec4_add(struct vec4 *out, const struct vec4 *in) +{ + out->x += in->x; + out->y += in->y; + out->z += in->z; + out->w += in->w; +} + +static inline void vec4_scale(struct vec4 *out, const float scale) +{ + out->x *= scale; + out->y *= scale; + out->z *= scale; + out->w *= scale; +} + +static void box_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch, + const struct volume *src_size, const struct pixel_format_desc *src_format, BYTE *dst, UINT dst_row_pitch, + UINT dst_slice_pitch, const struct volume *dst_size, const struct pixel_format_desc *dst_format, + const struct d3dx_color_key *color_key, const PALETTEENTRY *palette) +{ + /* Color keys are always represented in D3DFMT_A8R8G8B8 format. */ + const struct pixel_format_desc *ck_format = color_key ? get_d3dx_pixel_format_info(D3DX_PIXEL_FORMAT_B8G8R8A8_UNORM) : NULL; + struct argb_conversion_info conv_info, ck_conv_info; + struct d3dx_color color, tmp; + unsigned int i; + UINT x, y, z; + + TRACE("src %p, src_row_pitch %u, src_slice_pitch %u, src_size %p, src_format %p, dst %p, " + "dst_row_pitch %u, dst_slice_pitch %u, dst_size %p, dst_format %p, color_key %s, palette %p.\n", + src, src_row_pitch, src_slice_pitch, src_size, src_format, dst, dst_row_pitch, dst_slice_pitch, dst_size, + dst_format, debug_d3dx_color_key(color_key), palette); + + init_argb_conversion_info(src_format, dst_format, &conv_info); + + if (color_key) + init_argb_conversion_info(src_format, ck_format, &ck_conv_info); + + color.rgb_range = get_range_for_component_type(src_format->rgb_type); + color.a_range = get_range_for_component_type(src_format->a_type); + for (z = 0; z < src_size->depth; z += 2) + { + BYTE *dst_slice_ptr = dst + (z >> 1) * dst_slice_pitch; + const BYTE *src_slice_ptr = src + src_slice_pitch * z; + + for (y = 0; y < src_size->height; y += 2) + { + const BYTE *src_row_ptr = src_slice_ptr + src_row_pitch * y; + BYTE *dst_ptr = dst_slice_ptr + (y >> 1) * dst_row_pitch; + + for (x = 0; x < src_size->width; x += 2) + { + const BYTE *src_ptr = src_row_ptr + x * src_format->bytes_per_pixel; + + memset(&color.value, 0, sizeof(color.value)); + for (i = 0; i < (src_size->depth > 1 ? 2 : 1); ++i) + { + const BYTE *ptr = src_ptr + i * src_slice_pitch; + + format_to_d3dx_color(src_format, ptr, palette, &tmp); + if (color_key) + check_color_key(&tmp, color_key, ck_format); + vec4_add(&color.value, &tmp.value); + + format_to_d3dx_color(src_format, ptr + src_format->bytes_per_pixel, palette, &tmp); + if (color_key) + check_color_key(&tmp, color_key, ck_format); + vec4_add(&color.value, &tmp.value); + + ptr += src_row_pitch; + format_to_d3dx_color(src_format, ptr, palette, &tmp); + if (color_key) + check_color_key(&tmp, color_key, ck_format); + vec4_add(&color.value, &tmp.value); + + format_to_d3dx_color(src_format, ptr + src_format->bytes_per_pixel, palette, &tmp); + if (color_key) + check_color_key(&tmp, color_key, ck_format); + vec4_add(&color.value, &tmp.value); + } + + vec4_scale(&color.value, src_size->depth > 1 ? 0.125f : 0.25f); + format_from_d3dx_color(dst_format, &color, dst_ptr); + dst_ptr += dst_format->bytes_per_pixel; + } + } + } +} + static HRESULT d3dx_pixels_decompress(struct d3dx_pixels *pixels, const struct pixel_format_desc *desc, BOOL is_dst, void **out_memory, uint32_t *out_row_pitch, uint32_t *out_slice_pitch, const struct pixel_format_desc **out_desc) @@ -3046,6 +3169,18 @@ HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, return E_NOTIMPL; }
+ /* + * Check to see if we potentially need to change to linear or triangle + * filtering. + */ + if ((filter_flags & 0xf) == D3DX_FILTER_BOX) + { + if (d3dx_size_is_half(&src_size, &dst_size)) + filter_flags = !d3dx_size_is_pow2(&src_size) ? ((filter_flags & ~0xf) | D3DX_FILTER_LINEAR) : filter_flags; + else + filter_flags = (filter_flags & ~0xf) | D3DX_FILTER_TRIANGLE; + } + if (is_index_format(src_desc) && (src_desc->block_width > 1)) { uint32_t unpacked_row_pitch, unpacked_slice_pitch; @@ -3147,6 +3282,12 @@ HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, (BYTE *)dst_pixels->data, dst_pixels->row_pitch, dst_pixels->slice_pitch, &dst_size, dst_desc, d3dx_ck, src_pixels->palette); } + else if ((filter_flags & 0xf) == D3DX_FILTER_BOX) + { + box_filter_argb_pixels(src_pixels->data, src_pixels->row_pitch, src_pixels->slice_pitch, &src_size, + src_desc, (BYTE *)dst_pixels->data, dst_pixels->row_pitch, dst_pixels->slice_pitch, &dst_size, + dst_desc, d3dx_ck, src_pixels->palette); + } else /* if ((filter & 0xf) == D3DX_FILTER_POINT) */ { if ((filter_flags & 0xf) != D3DX_FILTER_POINT) diff --git a/dlls/d3dx9_36/d3dx_helpers.h b/dlls/d3dx9_36/d3dx_helpers.h index 16cadadc94b..d5523cab1ed 100644 --- a/dlls/d3dx9_36/d3dx_helpers.h +++ b/dlls/d3dx9_36/d3dx_helpers.h @@ -394,6 +394,12 @@ static inline BOOL is_conversion_to_supported(const struct pixel_format_desc *fo && !is_unknown_format(format); }
+/* Returns TRUE if num is a power of 2, FALSE if not, or if 0 */ +static inline BOOL is_pow2(UINT num) +{ + return !(num & (num - 1)); +} + HRESULT d3dx_validate_filter(uint32_t filter);
const struct pixel_format_desc *get_d3dx_pixel_format_info(enum d3dx_pixel_format_id format); diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 20f3866ded3..c72c4a01877 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -5172,7 +5172,7 @@ static void test_image_filters(void) { a8r8g8b8_16_16_linear_filter_8_8, .todo = TRUE }, { a8r8g8b8_16_16_triangle_filter_8_8, a8r8g8b8_16_16_triangle_filter_8_8_32bit, .todo = TRUE }, /* Linear and box filters match. */ - { a8r8g8b8_16_16_linear_filter_8_8, .todo = TRUE }, + { a8r8g8b8_16_16_linear_filter_8_8 }, }, }, { diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index a87152fc2ac..74f8b2fc85e 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -1243,7 +1243,7 @@ static void test_D3DXFilterTexture(IDirect3DDevice9 *device) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
IDirect3DTexture9_LockRect(tex, 1, &lock_rect, NULL, D3DLOCK_READONLY); - todo_wine check_test_readback(lock_rect.pBits, lock_rect.Pitch, 0, a8r8g8b8_16_16_linear_filter_8_8, 8, 8, 1, + check_test_readback(lock_rect.pBits, lock_rect.Pitch, 0, a8r8g8b8_16_16_linear_filter_8_8, 8, 8, 1, D3DFMT_A8R8G8B8, 0); IDirect3DTexture9_UnlockRect(tex, 1); IDirect3DTexture9_Release(tex); @@ -1310,12 +1310,12 @@ static void test_D3DXFilterTexture(IDirect3DDevice9 *device) IDirect3DVolumeTexture9_LockBox(voltex, 1, &lock_box, NULL, D3DLOCK_READONLY); if (sizeof(void *) == 4) { - todo_wine check_test_readback(lock_box.pBits, lock_box.RowPitch, lock_box.SlicePitch, - a8r8g8b8_8_8_8_box_filter_4_4_4_32bit, 4, 4, 4, D3DFMT_A8R8G8B8, 0); + check_test_readback(lock_box.pBits, lock_box.RowPitch, lock_box.SlicePitch, + a8r8g8b8_8_8_8_box_filter_4_4_4_32bit, 4, 4, 4, D3DFMT_A8R8G8B8, 1); } else { - todo_wine check_test_readback(lock_box.pBits, lock_box.RowPitch, lock_box.SlicePitch, + check_test_readback(lock_box.pBits, lock_box.RowPitch, lock_box.SlicePitch, a8r8g8b8_8_8_8_linear_filter_4_4_4, 4, 4, 4, D3DFMT_A8R8G8B8, 0); } IDirect3DVolumeTexture9_UnlockBox(voltex, 1); diff --git a/dlls/d3dx9_36/tests/volume.c b/dlls/d3dx9_36/tests/volume.c index 9ed435e5edd..c0bde08c93a 100644 --- a/dlls/d3dx9_36/tests/volume.c +++ b/dlls/d3dx9_36/tests/volume.c @@ -684,6 +684,7 @@ static void test_image_filters(void) const void *expected_dst_data; const void *expected_dst_data_32; BOOL todo; + uint32_t max_diff; } filter_expected[4]; } tests[] = @@ -700,7 +701,10 @@ static void test_image_filters(void) /* Linear and box filters match on 64bit, but not 32bit. */ { a8r8g8b8_8_8_8_linear_filter_4_4_4, a8r8g8b8_8_8_8_box_filter_4_4_4_32bit, - .todo = TRUE +#ifndef _WIN64 + /* We match exactly on 64-bit, but not 32-bit. */ + .max_diff = 1 +#endif }, }, }, @@ -756,7 +760,7 @@ static void test_image_filters(void) IDirect3DVolume9_LockBox(volume, &locked_box, NULL, D3DLOCK_READONLY); todo_wine_if(tests[i].filter_expected[j].todo) check_test_readback(locked_box.pBits, locked_box.RowPitch, locked_box.SlicePitch, expected_dst, tests[i].dst_width, tests[i].dst_height, tests[i].dst_depth, - tests[i].format, 0); + tests[i].format, tests[i].filter_expected[j].max_diff); IDirect3DVolume9_UnlockBox(volume);
winetest_pop_context(); diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index 0873b686497..799ff1e82ca 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -24,12 +24,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
-/* Returns TRUE if num is a power of 2, FALSE if not, or if 0 */ -static BOOL is_pow2(UINT num) -{ - return !(num & (num - 1)); -} - static HRESULT get_surface(D3DRESOURCETYPE type, struct IDirect3DBaseTexture9 *tex, int face, UINT level, struct IDirect3DSurface9 **surf) {