From: Connor McAdams <cmcadams@codeweavers.com> Signed-off-by: Connor McAdams <cmcadams@codeweavers.com> --- dlls/d3dx10_43/tests/d3dx10.c | 4 ++-- dlls/d3dx11_43/tests/d3dx11.c | 4 ++-- dlls/d3dx9_36/d3dx_helpers.c | 43 +++++++++++++++++++++++++++++++++++ dlls/d3dx9_36/d3dx_helpers.h | 2 ++ dlls/d3dx9_36/tests/surface.c | 12 +++++----- 5 files changed, 55 insertions(+), 10 deletions(-) diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 26d5d65c200..252a64cddd2 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -5868,7 +5868,7 @@ static void test_srgb_filter_flags(void) }, { 2, 2, test_a8r8g8b8, NULL, DXGI_FORMAT_R8G8B8A8_UNORM, D3DX10_FILTER_NONE | D3DX10_FILTER_SRGB_IN, - test_a8r8g8b8_srgb_in_expected, NULL, DXGI_FORMAT_R8G8B8A8_UNORM, .todo = TRUE + test_a8r8g8b8_srgb_in_expected, NULL, DXGI_FORMAT_R8G8B8A8_UNORM }, { 2, 2, test_a8r8g8b8, NULL, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, D3DX10_FILTER_NONE, @@ -5876,7 +5876,7 @@ static void test_srgb_filter_flags(void) }, { 2, 2, test_a8r8g8b8, NULL, DXGI_FORMAT_R8G8B8A8_UNORM, D3DX10_FILTER_NONE | D3DX10_FILTER_SRGB_OUT, - test_a8r8g8b8_srgb_out_expected, NULL, DXGI_FORMAT_R8G8B8A8_UNORM, .todo = TRUE + test_a8r8g8b8_srgb_out_expected, NULL, DXGI_FORMAT_R8G8B8A8_UNORM }, { 2, 2, test_a8r8g8b8, NULL, DXGI_FORMAT_R8G8B8A8_UNORM, D3DX10_FILTER_NONE, diff --git a/dlls/d3dx11_43/tests/d3dx11.c b/dlls/d3dx11_43/tests/d3dx11.c index 97f963ad59e..a56f415dced 100644 --- a/dlls/d3dx11_43/tests/d3dx11.c +++ b/dlls/d3dx11_43/tests/d3dx11.c @@ -4696,7 +4696,7 @@ static void test_srgb_filter_flags(void) }, { 2, 2, test_a8r8g8b8, NULL, DXGI_FORMAT_R8G8B8A8_UNORM, D3DX11_FILTER_NONE | D3DX11_FILTER_SRGB_IN, - test_a8r8g8b8_srgb_in_expected, NULL, DXGI_FORMAT_R8G8B8A8_UNORM, .todo = TRUE + test_a8r8g8b8_srgb_in_expected, NULL, DXGI_FORMAT_R8G8B8A8_UNORM }, { 2, 2, test_a8r8g8b8, NULL, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, D3DX11_FILTER_NONE, @@ -4704,7 +4704,7 @@ static void test_srgb_filter_flags(void) }, { 2, 2, test_a8r8g8b8, NULL, DXGI_FORMAT_R8G8B8A8_UNORM, D3DX11_FILTER_NONE | D3DX11_FILTER_SRGB_OUT, - test_a8r8g8b8_srgb_out_expected, NULL, DXGI_FORMAT_R8G8B8A8_UNORM, .todo = TRUE + test_a8r8g8b8_srgb_out_expected, NULL, DXGI_FORMAT_R8G8B8A8_UNORM }, { 2, 2, test_a8r8g8b8, NULL, DXGI_FORMAT_R8G8B8A8_UNORM, D3DX11_FILTER_NONE, diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c index 573a550b5b0..bff7798006d 100644 --- a/dlls/d3dx9_36/d3dx_helpers.c +++ b/dlls/d3dx9_36/d3dx_helpers.c @@ -73,6 +73,8 @@ static uint32_t d3dx_conv_flags_from_filter(uint32_t filter) if ((filter & D3DX_FILTER_PMA) && ((filter & D3DX_FILTER_PMA) != D3DX_FILTER_PMA)) conv_flags |= (filter & D3DX_FILTER_PMA_IN) ? CONV_FLAG_PM_ALPHA_IN : CONV_FLAG_PM_ALPHA_OUT; + if ((filter & D3DX_FILTER_SRGB) && ((filter & D3DX_FILTER_SRGB) != D3DX_FILTER_SRGB)) + conv_flags |= (filter & D3DX_FILTER_SRGB_IN) ? CONV_FLAG_SRGB_IN : CONV_FLAG_SRGB_OUT; return conv_flags; } @@ -2468,6 +2470,33 @@ static void straight_alpha_from_premultiplied_alpha(struct vec4 *vec) vec->z = (vec->w == 0.0f) ? 0.0f : vec->z / vec->w; } +/* + * All versions of d3dx (9-11) treat sRGB as "simplified sRGB." Rather + * than using the sRGB transfer function defined in IEC 61966-2-1:1999, they + * use a plain gamma 2.2 transfer function which ignores the special handling + * of the linear section near 0. + * + * Native d3dx also seems to use a lookup table to do this conversion, which + * matches the output of earlier versions of DirectXTex (prior to commit + * 98699f90f9177cee0f1be5ff441d0c42c32d9b69). If it's determined later on that + * an application needs to more closely match native's conversion values for + * formats larger than 8bpc this should be considered, but for now these + * functions result in matching native's output for 8bpc formats. + */ +static void srgb_from_linear_rgb(struct vec4 *vec) +{ + vec->x = powf(vec->x, 1.0f / 2.2f); + vec->y = powf(vec->y, 1.0f / 2.2f); + vec->z = powf(vec->z, 1.0f / 2.2f); +} + +static void linear_rgb_from_srgb(struct vec4 *vec) +{ + vec->x = powf(vec->x, 2.2f); + vec->y = powf(vec->y, 2.2f); + vec->z = powf(vec->z, 2.2f); +} + static void convert_argb_pixel(const uint8_t *src_ptr, const struct pixel_format_desc *src_fmt, uint8_t *dst_ptr, const struct pixel_format_desc *dst_fmt, const PALETTEENTRY *palette, struct argb_conversion_info *conv_info, const struct d3dx_color_key *color_key, @@ -2509,6 +2538,8 @@ static void convert_argb_pixel(const uint8_t *src_ptr, const struct pixel_format format_to_d3dx_color(src_fmt, src_ptr, palette, &color); if (conv_flags & CONV_FLAG_PM_ALPHA_IN) straight_alpha_from_premultiplied_alpha(&color.value); + if (conv_flags & CONV_FLAG_SRGB_IN) + linear_rgb_from_srgb(&color.value); tmp = color; if (color_key) @@ -2528,6 +2559,8 @@ static void convert_argb_pixel(const uint8_t *src_ptr, const struct pixel_format } color = tmp; + if (conv_flags & CONV_FLAG_SRGB_OUT) + srgb_from_linear_rgb(&color.value); if (conv_flags & CONV_FLAG_PM_ALPHA_OUT) premultiplied_alpha_from_straight_alpha(&color.value); format_from_d3dx_color(dst_fmt, &color, dst_ptr); @@ -2727,6 +2760,8 @@ static void box_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src format_to_d3dx_color(src_format, ptr, palette, &tmp); if (conv_flags & CONV_FLAG_PM_ALPHA_IN) straight_alpha_from_premultiplied_alpha(&color.value); + if (conv_flags & CONV_FLAG_SRGB_IN) + linear_rgb_from_srgb(&color.value); if (color_key) check_color_key(&tmp, color_key, ck_format); vec4_add(&color.value, &tmp.value); @@ -2734,6 +2769,8 @@ static void box_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src format_to_d3dx_color(src_format, ptr + src_format->bytes_per_pixel, palette, &tmp); if (conv_flags & CONV_FLAG_PM_ALPHA_IN) straight_alpha_from_premultiplied_alpha(&color.value); + if (conv_flags & CONV_FLAG_SRGB_IN) + linear_rgb_from_srgb(&color.value); if (color_key) check_color_key(&tmp, color_key, ck_format); vec4_add(&color.value, &tmp.value); @@ -2742,6 +2779,8 @@ static void box_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src format_to_d3dx_color(src_format, ptr, palette, &tmp); if (conv_flags & CONV_FLAG_PM_ALPHA_IN) straight_alpha_from_premultiplied_alpha(&color.value); + if (conv_flags & CONV_FLAG_SRGB_IN) + linear_rgb_from_srgb(&color.value); if (color_key) check_color_key(&tmp, color_key, ck_format); vec4_add(&color.value, &tmp.value); @@ -2749,12 +2788,16 @@ static void box_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src format_to_d3dx_color(src_format, ptr + src_format->bytes_per_pixel, palette, &tmp); if (conv_flags & CONV_FLAG_PM_ALPHA_IN) straight_alpha_from_premultiplied_alpha(&color.value); + if (conv_flags & CONV_FLAG_SRGB_IN) + linear_rgb_from_srgb(&color.value); 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); + if (conv_flags & CONV_FLAG_SRGB_OUT) + srgb_from_linear_rgb(&color.value); if (conv_flags & CONV_FLAG_PM_ALPHA_OUT) premultiplied_alpha_from_straight_alpha(&color.value); format_from_d3dx_color(dst_format, &color, dst_ptr); diff --git a/dlls/d3dx9_36/d3dx_helpers.h b/dlls/d3dx9_36/d3dx_helpers.h index 5b65f52cfa3..10cbc1723ed 100644 --- a/dlls/d3dx9_36/d3dx_helpers.h +++ b/dlls/d3dx9_36/d3dx_helpers.h @@ -246,6 +246,8 @@ enum conversion_flag { CONV_FLAG_PM_ALPHA_IN = 0x01, CONV_FLAG_PM_ALPHA_OUT = 0x02, + CONV_FLAG_SRGB_IN = 0x04, + CONV_FLAG_SRGB_OUT = 0x08, }; enum component_type diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 99a6af38ae8..ea01e3389a9 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -1394,7 +1394,7 @@ static void test_dxt_premultiplied_alpha(IDirect3DDevice9 *device) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); IDirect3DSurface9_LockRect(decomp_surf, &lock_rect, NULL, D3DLOCK_READONLY); - todo_wine check_test_readback(lock_rect.pBits, lock_rect.Pitch, 0, dxt_srgb_in_expected, 4, 4, 1, D3DFMT_A8R8G8B8, 1); + check_test_readback(lock_rect.pBits, lock_rect.Pitch, 0, dxt_srgb_in_expected, 4, 4, 1, D3DFMT_A8R8G8B8, 1); IDirect3DSurface9_UnlockRect(decomp_surf); /* DXT4, SRGB in. */ @@ -1403,7 +1403,7 @@ static void test_dxt_premultiplied_alpha(IDirect3DDevice9 *device) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); IDirect3DSurface9_LockRect(decomp_surf, &lock_rect, NULL, D3DLOCK_READONLY); - todo_wine check_test_readback(lock_rect.pBits, lock_rect.Pitch, 0, dxt_srgb_in_expected, 4, 4, 1, D3DFMT_A8R8G8B8, 1); + check_test_readback(lock_rect.pBits, lock_rect.Pitch, 0, dxt_srgb_in_expected, 4, 4, 1, D3DFMT_A8R8G8B8, 1); IDirect3DSurface9_UnlockRect(decomp_surf); /* @@ -1426,7 +1426,7 @@ static void test_dxt_premultiplied_alpha(IDirect3DDevice9 *device) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); IDirect3DSurface9_LockRect(decomp_surf, &lock_rect, NULL, D3DLOCK_READONLY); - todo_wine check_test_readback(lock_rect.pBits, lock_rect.Pitch, 0, dxt_srgb_out_expected, 4, 4, 1, D3DFMT_A8R8G8B8, 0); + check_test_readback(lock_rect.pBits, lock_rect.Pitch, 0, dxt_srgb_out_expected, 4, 4, 1, D3DFMT_A8R8G8B8, 0); IDirect3DSurface9_UnlockRect(decomp_surf); /* DXT4, SRGB out. */ @@ -1446,7 +1446,7 @@ static void test_dxt_premultiplied_alpha(IDirect3DDevice9 *device) ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); IDirect3DSurface9_LockRect(decomp_surf, &lock_rect, NULL, D3DLOCK_READONLY); - todo_wine check_test_readback(lock_rect.pBits, lock_rect.Pitch, 0, dxt_srgb_out_expected, 4, 4, 1, D3DFMT_A8R8G8B8, 0); + check_test_readback(lock_rect.pBits, lock_rect.Pitch, 0, dxt_srgb_out_expected, 4, 4, 1, D3DFMT_A8R8G8B8, 0); IDirect3DSurface9_UnlockRect(decomp_surf); IDirect3DSurface9_Release(decomp_surf); @@ -5432,11 +5432,11 @@ static void test_srgb_filter_flags(void) }, { { 0, 0, 2, 2 }, test_a8r8g8b8, D3DFMT_A8R8G8B8, D3DX_FILTER_NONE | D3DX_FILTER_SRGB_IN, - test_a8r8g8b8_srgb_in_expected, .todo = TRUE + test_a8r8g8b8_srgb_in_expected }, { { 0, 0, 2, 2 }, test_a8r8g8b8, D3DFMT_A8R8G8B8, D3DX_FILTER_NONE | D3DX_FILTER_SRGB_OUT, - test_a8r8g8b8_srgb_out_expected, .todo = TRUE + test_a8r8g8b8_srgb_out_expected }, { { 0, 0, 2, 2 }, test_float4_srgb_in, D3DFMT_A32B32G32R32F, D3DX_FILTER_NONE | D3DX_FILTER_SRGB_IN, -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10513