From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 6 ++- dlls/d3dx9_36/surface.c | 40 ++++++++++++++- dlls/d3dx9_36/tests/surface.c | 92 +++++++++++++++++------------------ dlls/d3dx9_36/util.c | 1 + 4 files changed, 87 insertions(+), 52 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 5ee956f041d..2338909f7cc 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -58,6 +58,7 @@ struct vec4 enum range { RANGE_FULL = 0, RANGE_UNORM = 1, + RANGE_SNORM = 2, };
struct d3dx_color @@ -85,6 +86,7 @@ enum format_type { FORMAT_ARGB, /* unsigned */ FORMAT_ARGBF16,/* float 16 */ FORMAT_ARGBF, /* float */ + FORMAT_ARGB_SNORM, FORMAT_DXT, FORMAT_INDEX, FORMAT_UNKNOWN @@ -168,7 +170,7 @@ extern const struct ID3DXIncludeVtbl d3dx_include_from_file_vtbl; static inline BOOL is_conversion_from_supported(const struct pixel_format_desc *format) { if (format->type == FORMAT_ARGB || format->type == FORMAT_ARGBF16 - || format->type == FORMAT_ARGBF || format->type == FORMAT_DXT) + || format->type == FORMAT_ARGBF || format->type == FORMAT_DXT || format->type == FORMAT_ARGB_SNORM) return TRUE; return !!format->to_rgba; } @@ -176,7 +178,7 @@ static inline BOOL is_conversion_from_supported(const struct pixel_format_desc * static inline BOOL is_conversion_to_supported(const struct pixel_format_desc *format) { if (format->type == FORMAT_ARGB || format->type == FORMAT_ARGBF16 - || format->type == FORMAT_ARGBF || format->type == FORMAT_DXT) + || format->type == FORMAT_ARGBF || format->type == FORMAT_DXT || format->type == FORMAT_ARGB_SNORM) return TRUE; return !!format->from_rgba; } diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 1b34bdb36f8..bf828ddca7b 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1521,6 +1521,9 @@ void format_to_d3dx_color(const struct pixel_format_desc *format, const BYTE *sr case FORMAT_INDEX: dst->range = RANGE_UNORM; break; + case FORMAT_ARGB_SNORM: + dst->range = RANGE_SNORM; + break; default: /* Shouldn't pass FORMAT_DXT/FORMAT_UNKNOWN into here. */ assert(0); break; @@ -1542,6 +1545,26 @@ void format_to_d3dx_color(const struct pixel_format_desc *format, const BYTE *sr *dst_component = float_16_to_32(tmp); else if (format->type == FORMAT_ARGBF) *dst_component = *(float *)&tmp; + else if (format->type == FORMAT_ARGB_SNORM) + { + const uint32_t sign_bit = (1u << (format->bits[c] - 1)); + uint32_t tmp_extended, tmp_masked = (tmp >> format->shift[c] % 8) & mask; + + tmp_extended = tmp_masked; + if (tmp_masked & sign_bit) + { + tmp_extended |= ~(sign_bit - 1); + + /* + * In order to clamp to an even range, we need to ignore + * the maximum negative value. + */ + if (tmp_masked == sign_bit) + tmp_extended |= 1; + } + + *dst_component = (float)(((int32_t)tmp_extended)) / (sign_bit - 1); + } else *dst_component = (float)((tmp >> format->shift[c] % 8) & mask) / mask; } @@ -1572,11 +1595,24 @@ static void format_from_d3dx_color(const struct pixel_format_desc *format, const v = float_32_to_16(src_component); else if (format->type == FORMAT_ARGBF) v = *(DWORD *)&src_component; + else if (format->type == FORMAT_ARGB_SNORM) + { + const uint32_t max_value = (1u << (format->bits[c] - 1)) - 1; + float val = src_component; + + if (src->range == RANGE_UNORM) + val = (val * 2.0f) - 1.0f; + + v = d3dx_clamp(val, -1.0f, 1.0f) * max_value + 0.5f; + } else { - float val = d3dx_clamp(src_component, 0.0f, 1.0f); + float val = src_component; + + if (src->range == RANGE_SNORM) + val = (val + 1.0f) / 2.0f;
- v = val * ((1u << format->bits[c]) - 1) + 0.5f; + v = d3dx_clamp(val, 0.0f, 1.0f) * ((1u << format->bits[c]) - 1) + 0.5f; }
for (i = format->shift[c] / 8 * 8; i < format->shift[c] + format->bits[c]; i += 8) diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 74c67b71581..804dfd7c874 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -1676,18 +1676,16 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) /* From a signed normalized format to an unsigned normalized format. */ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_q8w8v8u8, D3DFMT_Q8W8V8U8, 8, NULL, &rect, D3DX_FILTER_NONE, 0); - todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - { - hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); - ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); - check_pixel_4bpp(&lockrect, 0, 0, 0xb08090a0); - check_pixel_4bpp(&lockrect, 1, 0, 0xffc0d0e0); - check_pixel_4bpp(&lockrect, 0, 1, 0x2f00001f); - check_pixel_4bpp(&lockrect, 1, 1, 0x7e3f4f5f); - hr = IDirect3DSurface9_UnlockRect(surf); - ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); - } + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + check_pixel_4bpp(&lockrect, 0, 0, 0xb08090a0); + check_pixel_4bpp(&lockrect, 1, 0, 0xffc0d0e0); + check_pixel_4bpp(&lockrect, 0, 1, 0x2f00001f); + check_pixel_4bpp(&lockrect, 1, 1, 0x7e3f4f5f); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr);
hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a32b32g32r32f, D3DFMT_A32B32G32R32F, 32, NULL, &rect, D3DX_FILTER_NONE, 0); @@ -1928,18 +1926,16 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_q8w8v8u8, D3DFMT_Q8W8V8U8, 8, NULL, &rect, D3DX_FILTER_NONE, 0); - todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - { - hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); - ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); - check_pixel_2bpp(&lockrect, 0, 0, 0xb08d); - check_pixel_2bpp(&lockrect, 1, 0, 0xffce); - check_pixel_2bpp(&lockrect, 0, 1, 0x2f02); - check_pixel_2bpp(&lockrect, 1, 1, 0x7e4d); - hr = IDirect3DSurface9_UnlockRect(surf); - ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); - } + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); + check_pixel_2bpp(&lockrect, 0, 0, 0xb08d); + check_pixel_2bpp(&lockrect, 1, 0, 0xffce); + check_pixel_2bpp(&lockrect, 0, 1, 0x2f02); + check_pixel_2bpp(&lockrect, 1, 1, 0x7e4d); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr);
hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a32b32g32r32f, D3DFMT_A32B32G32R32F, 32, NULL, &rect, D3DX_FILTER_NONE, 0); @@ -2204,14 +2200,14 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) /* Signed normalized value to full range float. */ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_q8w8v8u8, D3DFMT_Q8W8V8U8, 8, NULL, &rect, D3DX_FILTER_NONE, 0); - todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); - check_pixel_float4(&lockrect, 0, 0, 0.00000000e+000f, 1.25984251e-001f, 2.51968503e-001f, 3.77952754e-001f, 0, TRUE); - check_pixel_float4(&lockrect, 1, 0, 5.03937006e-001f, 6.29921257e-001f, 7.55905509e-001f, 1.00000000e+000f, 0, TRUE); - check_pixel_float4(&lockrect, 0, 1, -1.00000000e+000f, -1.00000000e+000f, -7.55905509e-001f, -6.29921257e-001f, 0, TRUE); - check_pixel_float4(&lockrect, 1, 1, -5.03937006e-001f, -3.77952754e-001f, -2.51968503e-001f, -7.87401572e-003f, 0, TRUE); + check_pixel_float4(&lockrect, 0, 0, 0.00000000e+000f, 1.25984251e-001f, 2.51968503e-001f, 3.77952754e-001f, 0, FALSE); + check_pixel_float4(&lockrect, 1, 0, 5.03937006e-001f, 6.29921257e-001f, 7.55905509e-001f, 1.00000000e+000f, 0, FALSE); + check_pixel_float4(&lockrect, 0, 1, -1.00000000e+000f, -1.00000000e+000f, -7.55905509e-001f, -6.29921257e-001f, 0, FALSE); + check_pixel_float4(&lockrect, 1, 1, -5.03937006e-001f, -3.77952754e-001f, -2.51968503e-001f, -7.87401572e-003f, 0, FALSE); hr = IDirect3DSurface9_UnlockRect(surf); ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr);
@@ -2289,53 +2285,53 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) SetRect(&rect, 0, 0, 2, 2); hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_q8w8v8u8, D3DFMT_Q8W8V8U8, 8, NULL, &rect, D3DX_FILTER_NONE, 0); - todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); - todo_wine check_pixel_4bpp(&lockrect, 0, 0, pixdata_q8w8v8u8[0]); - todo_wine check_pixel_4bpp(&lockrect, 1, 0, pixdata_q8w8v8u8[1]); - todo_wine check_pixel_4bpp(&lockrect, 0, 1, pixdata_q8w8v8u8[2]); - todo_wine check_pixel_4bpp(&lockrect, 1, 1, pixdata_q8w8v8u8[3]); + check_pixel_4bpp(&lockrect, 0, 0, pixdata_q8w8v8u8[0]); + check_pixel_4bpp(&lockrect, 1, 0, pixdata_q8w8v8u8[1]); + check_pixel_4bpp(&lockrect, 0, 1, pixdata_q8w8v8u8[2]); + check_pixel_4bpp(&lockrect, 1, 1, pixdata_q8w8v8u8[3]); hr = IDirect3DSurface9_UnlockRect(surf); ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr);
/* Unorm to snorm. */ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8, D3DFMT_A8B8G8R8, 8, NULL, &rect, D3DX_FILTER_NONE, 0); - todo_wine ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); - todo_wine check_pixel_4bpp(&lockrect, 0, 0, 0x43bbce70); - todo_wine check_pixel_4bpp(&lockrect, 1, 0, 0xa5dc6812); - todo_wine check_pixel_4bpp(&lockrect, 0, 1, 0x8b31177d); - todo_wine check_pixel_4bpp(&lockrect, 1, 1, 0x0d43ad76); + check_pixel_4bpp(&lockrect, 0, 0, 0x43bbce70); + check_pixel_4bpp(&lockrect, 1, 0, 0xa5dc6812); + check_pixel_4bpp(&lockrect, 0, 1, 0x8b31177d); + check_pixel_4bpp(&lockrect, 1, 1, 0x0d43ad76); hr = IDirect3DSurface9_UnlockRect(surf); ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr);
/* Full range float to snorm. */ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a32b32g32r32f, D3DFMT_A32B32G32R32F, 32, NULL, &rect, D3DX_FILTER_NONE, 0); - todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); - todo_wine check_pixel_4bpp(&lockrect, 0, 0, 0x7f7f0d00); - todo_wine check_pixel_4bpp(&lockrect, 1, 0, 0x7f7f7f7f); - todo_wine check_pixel_4bpp(&lockrect, 0, 1, 0x827fe8f4); - todo_wine check_pixel_4bpp(&lockrect, 1, 1, 0x82828282); + check_pixel_4bpp(&lockrect, 0, 0, 0x7f7f0d00); + check_pixel_4bpp(&lockrect, 1, 0, 0x7f7f7f7f); + check_pixel_4bpp(&lockrect, 0, 1, 0x827fe8f4); + check_pixel_4bpp(&lockrect, 1, 1, 0x82828282); hr = IDirect3DSurface9_UnlockRect(surf); ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr);
/* Unorm alpha and unorm luma to snorm. */ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8l8, D3DFMT_A8L8, 4, NULL, &rect, D3DX_FILTER_NONE, 0); - todo_wine ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); ok(hr == D3D_OK, "Failed to lock surface, hr %#lx.\n", hr); - todo_wine check_pixel_4bpp(&lockrect, 0, 0, 0x7f828282); - todo_wine check_pixel_4bpp(&lockrect, 1, 0, 0x827f7f7f); - todo_wine check_pixel_4bpp(&lockrect, 0, 1, 0x7fb2b2b2); + check_pixel_4bpp(&lockrect, 0, 0, 0x7f828282); + check_pixel_4bpp(&lockrect, 1, 0, 0x827f7f7f); + check_pixel_4bpp(&lockrect, 0, 1, 0x7fb2b2b2); check_pixel_4bpp(&lockrect, 1, 1, 0x00000000); hr = IDirect3DSurface9_UnlockRect(surf); ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr); diff --git a/dlls/d3dx9_36/util.c b/dlls/d3dx9_36/util.c index 419bd92884a..4519fd02f17 100644 --- a/dlls/d3dx9_36/util.c +++ b/dlls/d3dx9_36/util.c @@ -88,6 +88,7 @@ static const struct pixel_format_desc formats[] = {D3DFMT_G32R32F, { 0, 32, 32, 0}, { 0, 0, 32, 0}, 8, 1, 1, 8, FORMAT_ARGBF, NULL, NULL }, {D3DFMT_A32B32G32R32F, {32, 32, 32, 32}, {96, 0, 32, 64}, 16, 1, 1, 16, FORMAT_ARGBF, NULL, NULL }, {D3DFMT_P8, { 8, 8, 8, 8}, { 0, 0, 0, 0}, 1, 1, 1, 1, FORMAT_INDEX, NULL, index_to_rgba}, + {D3DFMT_Q8W8V8U8, { 8, 8, 8, 8}, {24, 0, 8, 16}, 4, 1, 1, 4, FORMAT_ARGB_SNORM, NULL, NULL }, /* marks last element */ {D3DFMT_UNKNOWN, { 0, 0, 0, 0}, { 0, 0, 0, 0}, 0, 1, 1, 0, FORMAT_UNKNOWN, NULL, NULL }, };