From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 8 +-- dlls/d3dx9_36/surface.c | 48 +++++++++++++++--- dlls/d3dx9_36/tests/surface.c | 92 +++++++++++++++++------------------ dlls/d3dx9_36/texture.c | 6 +-- dlls/d3dx9_36/util.c | 1 + 5 files changed, 94 insertions(+), 61 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 7ddc3b06764..97db64655dc 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -76,6 +76,7 @@ enum format_type { FORMAT_ARGBF, /* float */ FORMAT_DXT, FORMAT_INDEX, + FORMAT_ARGB_SNORM, FORMAT_UNKNOWN };
@@ -157,7 +158,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; } @@ -165,7 +166,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; } @@ -179,7 +180,8 @@ const struct pixel_format_desc *get_format_info(D3DFORMAT format); const struct pixel_format_desc *get_format_info_idx(int idx);
void format_to_vec4(const struct pixel_format_desc *format, const BYTE *src, struct vec4 *dst); -void format_from_vec4(const struct pixel_format_desc *format, const struct vec4 *src, BYTE *dst); +void format_from_vec4(const struct pixel_format_desc *format, const struct vec4 *src, enum format_type src_type, + BYTE *dst);
void copy_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch, BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, const struct volume *size, diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 9b24bf08e5c..d36018541d9 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1524,6 +1524,26 @@ void format_to_vec4(const struct pixel_format_desc *format, const BYTE *src, str *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 = (1 << (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; } @@ -1533,7 +1553,8 @@ void format_to_vec4(const struct pixel_format_desc *format, const BYTE *src, str }
/* It doesn't work for components bigger than 32 bits. */ -void format_from_vec4(const struct pixel_format_desc *format, const struct vec4 *src, BYTE *dst) +void format_from_vec4(const struct pixel_format_desc *format, const struct vec4 *src, enum format_type src_type, + BYTE *dst) { DWORD v, mask32; unsigned int c, i; @@ -1554,11 +1575,24 @@ void format_from_vec4(const struct pixel_format_desc *format, const struct vec4 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 = (1 << (format->bits[c] - 1)) - 1; + float val = src_component; + + if (src_type == FORMAT_ARGB) + 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_type == FORMAT_ARGB_SNORM) + val = (val + 1.0f) / 2.0f;
- v = val * ((1 << format->bits[c]) - 1) + 0.5f; + v = d3dx_clamp(val, 0.0f, 1.0f) * ((1 << format->bits[c]) - 1) + 0.5f; }
for (i = format->shift[c] / 8 * 8; i < format->shift[c] + format->bits[c]; i += 8) @@ -1691,7 +1725,7 @@ void convert_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pit { DWORD ck_pixel;
- format_from_vec4(ck_format, &tmp, (BYTE *)&ck_pixel); + format_from_vec4(ck_format, &tmp, src_format->type, (BYTE *)&ck_pixel); if (ck_pixel == color_key) tmp.w = 0.0f; } @@ -1701,7 +1735,7 @@ void convert_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pit else color = tmp;
- format_from_vec4(dst_format, &color, dst_ptr); + format_from_vec4(dst_format, &color, src_format->type, dst_ptr); }
src_ptr += src_format->bytes_per_pixel; @@ -1799,7 +1833,7 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic { DWORD ck_pixel;
- format_from_vec4(ck_format, &tmp, (BYTE *)&ck_pixel); + format_from_vec4(ck_format, &tmp, src_format->type, (BYTE *)&ck_pixel); if (ck_pixel == color_key) tmp.w = 0.0f; } @@ -1809,7 +1843,7 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic else color = tmp;
- format_from_vec4(dst_format, &color, dst_ptr); + format_from_vec4(dst_format, &color, src_format->type, dst_ptr); }
dst_ptr += dst_format->bytes_per_pixel; diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 867bb8006a3..9bc067f1222 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -1615,18 +1615,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); @@ -1867,18 +1865,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); @@ -2143,14 +2139,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.0f, 0.125984f, 0.251969f, 0.377953f, TRUE); - check_pixel_float4(&lockrect, 1, 0, 0.503937f, 0.629921f, 0.755906f, 1.0f, TRUE); - check_pixel_float4(&lockrect, 0, 1, -1.0f, -1.0f, -0.755906f, -0.629921f, TRUE); - check_pixel_float4(&lockrect, 1, 1, -0.503937f, -0.377953f, -0.251969f, -0.007874f, TRUE); + check_pixel_float4(&lockrect, 0, 0, 0.0f, 0.125984f, 0.251969f, 0.377953f, FALSE); + check_pixel_float4(&lockrect, 1, 0, 0.503937f, 0.629921f, 0.755906f, 1.0f, FALSE); + check_pixel_float4(&lockrect, 0, 1, -1.0f, -1.0f, -0.755906f, -0.629921f, FALSE); + check_pixel_float4(&lockrect, 1, 1, -0.503937f, -0.377953f, -0.251969f, -0.007874f, FALSE); hr = IDirect3DSurface9_UnlockRect(surf); ok(hr == D3D_OK, "Failed to unlock surface, hr %#lx.\n", hr);
@@ -2226,53 +2222,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, "D3DXLoadSurfaceFromMemory returned %#lx, expected %#lx\n", hr, D3D_OK); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#lx, expected %#lx\n", hr, D3D_OK); 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, 0x26190d00); - todo_wine check_pixel_4bpp(&lockrect, 1, 0, 0x7f7f7f7f); - todo_wine check_pixel_4bpp(&lockrect, 0, 1, 0xcedbe8f4); - todo_wine check_pixel_4bpp(&lockrect, 1, 1, 0x82828282); + check_pixel_4bpp(&lockrect, 0, 0, 0x26190d00); + check_pixel_4bpp(&lockrect, 1, 0, 0x7f7f7f7f); + check_pixel_4bpp(&lockrect, 0, 1, 0xcedbe8f4); + 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/texture.c b/dlls/d3dx9_36/texture.c index 29781ccd839..ce87feefe0b 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -1320,7 +1320,7 @@ HRESULT WINAPI D3DXFillTexture(struct IDirect3DTexture9 *texture, LPD3DXFILL2D f
function(&value, &coord, &size, funcdata);
- format_from_vec4(format, (const struct vec4 *)&value, dst); + format_from_vec4(format, (const struct vec4 *)&value, FORMAT_ARGBF, dst); } } if (FAILED(hr = unlock_surface(surface, NULL, temp_surface, TRUE))) @@ -1711,7 +1711,7 @@ HRESULT WINAPI D3DXFillCubeTexture(struct IDirect3DCubeTexture9 *texture, LPD3DX
function(&value, &coord, &size, funcdata);
- format_from_vec4(format, (const struct vec4 *)&value, dst); + format_from_vec4(format, (const struct vec4 *)&value, FORMAT_ARGBF, dst); } } IDirect3DCubeTexture9_UnlockRect(texture, f, m); @@ -1778,7 +1778,7 @@ HRESULT WINAPI D3DXFillVolumeTexture(struct IDirect3DVolumeTexture9 *texture, LP
function(&value, &coord, &size, funcdata);
- format_from_vec4(format, (const struct vec4 *)&value, dst); + format_from_vec4(format, (const struct vec4 *)&value, FORMAT_ARGBF, dst); } } } 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 }, };