This patch series adds support for using DXTn volume textures, by decompressing and converting them using the CPU. This fixes issues with games such as Halo Online, and others mentioned in the bugzilla page here: https://bugs.winehq.org/show_bug.cgi?id=39253
Let me know what needs changed or fixed, this is my first patch, so I assume it wont be perfect. :)
Thanks, Connor McAdams (Conmanx360 in IRC)
Connor McAdams (3): Add decompression functions for DXT1, DXT3, and DXT5 Add format change before upload for non-volume textures Add new test for DXTn volume textures.
dlls/d3d9/tests/visual.c | 190 +++++++++++++++++++--------- dlls/wined3d/texture.c | 26 ++++ dlls/wined3d/utils.c | 321 ++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 462 insertions(+), 75 deletions(-)
This adds decompression functions for DXT1, DXT3, and DXT5 formats, which covers all the possible DXT formats. These are used for decompressing DXTn volume textures, and converting them to b8g8r8a8. --- dlls/wined3d/utils.c | 321 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 305 insertions(+), 16 deletions(-)
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 937c1bc..ce1ccdf 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -840,6 +840,305 @@ static void convert_s8_uint_d24_float(const BYTE *src, BYTE *dst, UINT src_row_p } }
+static void dxt5_decompress_block(const BYTE *src, BYTE *dst, UINT width, UINT height, UINT depth, + unsigned int x_pos, unsigned int y_pos, unsigned int z_pos, UINT dst_slice_pitch, UINT64 cur_block) +{ + DWORD alpha_lookup; + DWORD bgra; + DWORD temp; + UINT64 alpha_block, alpha_index, color_block, color_index; + DWORD *Dest; + const UINT64 *Source; + unsigned short color[2]; + unsigned int i, x, y; + unsigned char alpha_val, color_val; + unsigned char alpha[8]; + unsigned char r[4]; + unsigned char g[4]; + unsigned char b[4]; + + Source = (const UINT64 *)(src + cur_block * 16); + alpha_block = Source[0]; + color_block = Source[1]; + + alpha[0] = alpha_block & 0xFF; + alpha[1] = (alpha_block >> 8) & 0xFF; + + /* Generate alpha lookup values */ + if (alpha[0] > alpha[1]) + { + for (i = 0; i < 6; i++) + alpha[2 + i] = (((6 - i) * alpha[0]) + ((1 + i) * alpha[1])) / 7; + } + else if (alpha[0] <= alpha[1]) + { + for (i = 0; i < 4; i++) + alpha[2 + i] = (((4 - i) * alpha[0]) + ((1 + i) * alpha[1])) / 5; + alpha[6] = 0; + alpha[7] = 255; + } + + /* Generate color lookup values */ + color[0] = color_block & 0xFFFF; + color[1] = (color_block >> 16) & 0xFFFF; + + for (i = 0; i < 2; i++) + { + temp = (color[i] >> 11) * 255 + 16; + r[i] = (temp / 32 + temp) / 32; + temp = ((color[i] >> 5) & 0x3F) * 255 + 32; + g[i] = (temp / 64 + temp) / 64; + temp = (color[i] & 0x1F) * 255 + 16; + b[i] = (temp / 32 + temp) / 32; + } + + for (i = 0; i < 2; i++) + { + r[2 + i] = (2 * r[0 + i] + r[1 - i]) / 3; + g[2 + i] = (2 * g[0 + i] + g[1 - i]) / 3; + b[2 + i] = (2 * b[0 + i] + b[1 - i]) / 3; + } + + color_index = (color_block >> 32) & 0xFFFFFFFF; + alpha_index = (alpha_block >> 16); + + Dest = (DWORD *)(dst + z_pos * dst_slice_pitch); + + for (y = 0; y < 4; y++) { + if (y_pos + y >= height) + break; + for (x = 0; x < 4; x++) { + if (x_pos + x >= width) + break; + + color_val = 0; + alpha_val = 0; + bgra = 0; + + color_val = (color_index >> (y * 8)); + color_val = (color_val >> (x * 2)) & 0x3; + alpha_lookup = (alpha_index >> (y * 12)) & 0xFFF; + alpha_val = (alpha_lookup >> (x * 3)) & 0x7; + bgra = ((alpha[alpha_val] << 24) | (r[color_val] << 16) | (g[color_val] << 8) | b[color_val]); + Dest[(y_pos + y) * width + (x_pos + x)] = bgra; + } + } +} + +static void convert_dxt5_b8g8r8a8_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch, + UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth) +{ + UINT64 current_block; + unsigned int x, y, z; + + current_block = 0; + + for (z = 0; z < depth; z++) + { + for (y = 0; y < height; y += 4) + { + for (x = 0; x < width; x += 4) + { + dxt5_decompress_block(src, dst, width, height, depth, x, y, z, dst_slice_pitch, current_block); + current_block++; + } + } + } +} + +static void dxt3_decompress_block(const BYTE *src, BYTE *dst, UINT width, UINT height, UINT depth, + unsigned int x_pos, unsigned int y_pos, unsigned int z_pos, UINT dst_slice_pitch, UINT64 cur_block) +{ + DWORD bgra; + DWORD temp; + UINT64 alpha_block, alpha_lookup, color_block, color_index; + DWORD *Dest; + const UINT64 *Source; + unsigned short color[2]; + unsigned int i, x, y; + unsigned char alpha_val, color_val; + unsigned char r[4]; + unsigned char g[4]; + unsigned char b[4]; + + Source = (const UINT64 *)(src + cur_block * 16); + alpha_block = Source[0]; + color_block = Source[1]; + + /* Generate color lookup values */ + color[0] = color_block & 0xFFFF; + color[1] = (color_block >> 16) & 0xFFFF; + + for (i = 0; i < 2; i++) + { + temp = (color[i] >> 11) * 255 + 16; + r[i] = (temp / 32 + temp) / 32; + temp = ((color[i] >> 5) & 0x3F) * 255 + 32; + g[i] = (temp / 64 + temp) / 64; + temp = (color[i] & 0x1F) * 255 + 16; + b[i] = (temp / 32 + temp) / 32; + } + + for (i = 0; i < 2; i++) + { + r[2 + i] = (2 * r[0 + i] + r[1 - i]) / 3; + g[2 + i] = (2 * g[0 + i] + g[1 - i]) / 3; + b[2 + i] = (2 * b[0 + i] + b[1 - i]) / 3; + } + + color_index = (color_block >> 32) & 0xFFFFFFFF; + Dest = (DWORD *)(dst + z_pos * dst_slice_pitch); + + for (y = 0; y < 4; y++) { + if (y_pos + y >= height) + break; + for (x = 0; x < 4; x++) { + if (x_pos + x >= width) + break; + + color_val = 0; + alpha_val = 0; + bgra = 0; + + color_val = (color_index >> (y * 8)); + color_val = (color_val >> (x * 2)) & 0x3; + + alpha_lookup = (alpha_block >> (y * 16)) & 0xFFFF; + alpha_val = (alpha_lookup >> (x * 4)) & 0xF; + temp = alpha_val * 255 + 8; + alpha_val = (temp / 16 + temp) / 16; + + bgra = ((alpha_val << 24) | (r[color_val] << 16) | (g[color_val] << 8) | b[color_val]); + Dest[(y_pos + y) * width + (x_pos + x)] = bgra; + } + } +} + +static void convert_dxt3_b8g8r8a8_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch, + UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth) +{ + UINT64 current_block; + unsigned int x, y, z; + + current_block = 0; + + for (z = 0; z < depth; z++) + { + for (y = 0; y < height; y += 4) + { + for (x = 0; x < width; x += 4) + { + dxt3_decompress_block(src, dst, width, height, depth, x, y, z, dst_slice_pitch, current_block); + current_block++; + } + } + } +} + +static void dxt1_decompress_block(const BYTE *src, BYTE *dst, UINT width, UINT height, UINT depth, + unsigned int x_pos, unsigned int y_pos, unsigned int z_pos, UINT dst_slice_pitch, UINT64 cur_block) +{ + DWORD bgra; + DWORD temp; + UINT64 color_block, color_index; + DWORD *Dest; + const UINT64 *Source; + unsigned short color[2]; + unsigned int i, x, y; + unsigned char color_val; + unsigned char alpha; + unsigned char r[4]; + unsigned char g[4]; + unsigned char b[4]; + unsigned char use_alpha; + + Source = (const UINT64 *)(src + cur_block * 8); + color_block = Source[0]; + + /* Generate color lookup values */ + color[0] = color_block & 0xFFFF; + color[1] = (color_block >> 16) & 0xFFFF; + + for (i = 0; i < 2; i++) + { + temp = (color[i] >> 11) * 255 + 16; + r[i] = (temp / 32 + temp) / 32; + temp = ((color[i] >> 5) & 0x3F) * 255 + 32; + g[i] = (temp / 64 + temp) / 64; + temp = (color[i] & 0x1F) * 255 + 16; + b[i] = (temp / 32 + temp) / 32; + } + + if (color[0] > color[1]) + { + for (i = 0; i < 2; i++) + { + r[2 + i] = (2 * r[0 + i] + r[1 - i]) / 3; + g[2 + i] = (2 * g[0 + i] + g[1 - i]) / 3; + b[2 + i] = (2 * b[0 + i] + b[1 - i]) / 3; + } + use_alpha = 0; + } + else if (color[0] <= color[1]) + { + r[2] = (r[0] + r[1]) / 2; + g[2] = (g[0] + g[1]) / 2; + b[2] = (b[0] + b[1]) / 2; + + r[3] = 0; + g[3] = 0; + b[3] = 0; + + use_alpha = 1; + } + + color_index = (color_block >> 32) & 0xFFFFFFFF; + Dest = (DWORD *)(dst + z_pos * dst_slice_pitch); + + for (y = 0; y < 4; y++) { + if (y_pos + y >= height) + break; + for (x = 0; x < 4; x++) { + if (x_pos + x >= width) + break; + + color_val = 0; + bgra = 0; + + color_val = (color_index >> (y * 8)); + color_val = (color_val >> (x * 2)) & 0x3; + if (color_val == 3 && use_alpha == 1) + alpha = 0; + else + alpha = 255; + + bgra = ((alpha << 24) | (r[color_val] << 16) | (g[color_val] << 8) | b[color_val]); + Dest[(y_pos + y) * width + (x_pos + x)] = bgra; + } + } +} + +static void convert_dxt1_b8g8r8a8_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch, + UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth) +{ + UINT64 current_block; + unsigned int x, y, z; + + current_block = 0; + + for (z = 0; z < depth; z++) + { + for (y = 0; y < height; y += 4) + { + for (x = 0; x < width; x += 4) + { + dxt1_decompress_block(src, dst, width, height, depth, x, y, z, dst_slice_pitch, current_block); + current_block++; + } + } + } +} + static void x8_d24_unorm_upload(const BYTE *src, BYTE *dst, unsigned int src_row_pitch, unsigned int src_slice_pitch, unsigned int dst_row_pitch, unsigned int dst_slice_pitch, @@ -1118,27 +1417,27 @@ static const struct wined3d_format_texture_info format_texture_info[] = GL_RGBA, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED, - EXT_TEXTURE_COMPRESSION_S3TC, NULL}, + EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt1_b8g8r8a8_unorm}, {WINED3DFMT_DXT2, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED, - EXT_TEXTURE_COMPRESSION_S3TC, NULL}, + EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt3_b8g8r8a8_unorm}, {WINED3DFMT_DXT3, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED, - EXT_TEXTURE_COMPRESSION_S3TC, NULL}, + EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt3_b8g8r8a8_unorm}, {WINED3DFMT_DXT4, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED, - EXT_TEXTURE_COMPRESSION_S3TC, NULL}, + EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt5_b8g8r8a8_unorm}, {WINED3DFMT_DXT5, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED, - EXT_TEXTURE_COMPRESSION_S3TC, NULL}, + EXT_TEXTURE_COMPRESSION_S3TC, convert_dxt5_b8g8r8a8_unorm}, {WINED3DFMT_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING @@ -3394,17 +3693,7 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_ * for dx9 GPUs support it, some do not, so not supporting DXTn volumes is OK for d3d9. * * Note that GL_NV_texture_compression_vtc adds this functionality to OpenGL, but the - * block layout is not compatible with the one used by d3d. See volume_dxt5_test. */ - idx = get_format_idx(WINED3DFMT_DXT1); - gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE; - idx = get_format_idx(WINED3DFMT_DXT2); - gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE; - idx = get_format_idx(WINED3DFMT_DXT3); - gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE; - idx = get_format_idx(WINED3DFMT_DXT4); - gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE; - idx = get_format_idx(WINED3DFMT_DXT5); - gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE; + * block layout is not compatible with the one used by d3d. See volume_dxtn_test. */ idx = get_format_idx(WINED3DFMT_BC1_UNORM); gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE; idx = get_format_idx(WINED3DFMT_BC1_UNORM_SRGB);
This patch keeps non-volume DXTn textures from being converted to b8g8r8a8. I have tested it and it does work converting them all, but the GPU can handle them normally. Volume textures are the only ones the GPU handles incorrectly. --- dlls/wined3d/texture.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index c316906..a998b9c 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -1948,6 +1948,32 @@ void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int s bo.addr += src_box->left * format->byte_count; }
+ if (format->id == WINED3DFMT_DXT5 || format->id == WINED3DFMT_DXT4 || + format->id == WINED3DFMT_DXT3 || format->id == WINED3DFMT_DXT2 || + format->id == WINED3DFMT_DXT1) + { + if (target == GL_TEXTURE_3D) + { + struct wined3d_format temp; + + f = *format; + temp.upload = f.upload; + format = &f; + format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM, WINED3DUSAGE_TEXTURE); + f = *format; + f.upload = temp.upload; + f.conv_byte_count = 4; + format = &f; + texture->resource.format_flags &= ~WINED3DFMT_FLAG_BLOCKS; + } + else + { + f = *format; + f.upload = NULL; + format = &f; + } + } + if (format->upload) { unsigned int dst_row_pitch, dst_slice_pitch;
To properly test the functionality of DXTn volume textures, I have added new tests for DXT1, DXT3, and DXT5 replacing the old DXT5 test. I also added a function to get the alpha values of pixels, although there may have been a reason one wasn't included in the first place, it's the only real way to make sure the alpha is behaving properly on the formats. --- dlls/d3d9/tests/visual.c | 190 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 131 insertions(+), 59 deletions(-)
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index b36c189..ec121b0 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -186,6 +186,31 @@ static void release_surface_readback(struct surface_readback *rb) IDirect3DSurface9_Release(rb->surface); }
+static DWORD getAlphaPixelColor(IDirect3DDevice9 *device, UINT x, UINT y) +{ + DWORD ret; + IDirect3DSurface9 *rt; + struct surface_readback rb; + HRESULT hr; + + hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt); + if(FAILED(hr)) + { + trace("Can't get the render target, hr %#x.\n", hr); + return 0xdeadbeed; + } + + get_rt_readback(rt, &rb); + /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't + * really important for these tests + */ + ret = get_readback_color(&rb, x, y) & 0xffffffff; + release_surface_readback(&rb); + + IDirect3DSurface9_Release(rt); + return ret; +} + static DWORD getPixelColor(IDirect3DDevice9 *device, UINT x, UINT y) { DWORD ret; @@ -17741,22 +17766,39 @@ done: DestroyWindow(window); }
-static void volume_dxt5_test(void) +static void volume_dxtn_test(void) { IDirect3DVolumeTexture9 *texture; IDirect3DDevice9 *device; D3DLOCKED_BOX box; IDirect3D9 *d3d; - unsigned int i; + unsigned int i, x; ULONG refcount; DWORD color; HWND window; HRESULT hr;
- static const char texture_data[] = + static const char dxt1_texture_data[] = + { + /* A 8x4x2 texture consisting of 4 4x4 blocks. The colors of the blocks are red, green, blue and white. */ + 0x00, 0xF8, 0x00, 0xF8, 0xF0, 0xF0, 0xF0, 0xF0, + 0xE0, 0x07, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 + }; + static const char dxt3_texture_data[] = + { + /* A 8x4x2 texture consisting of 4 4x4 blocks. The colors of the blocks are red, green, blue and white. The red block goes from + * 15 to 0 on alpha level. */ + 0xFF, 0xEE, 0xFF, 0xEE, 0xFF, 0xEE, 0xFF, 0xEE, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xDD, 0xFF, 0xDD, 0xFF, 0xDD, 0xFF, 0xDD, 0xe0, 0x07, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xBB, 0xFF, 0xBB, 0xFF, 0xBB, 0xFF, 0xBB, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 + }; + static const char dxt5_texture_data[] = { /* A 8x4x2 texture consisting of 4 4x4 blocks. The colors of the blocks are red, green, blue and white. */ - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x80, 0x0D, 0xD8, 0x80, 0x0D, 0xD8, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 @@ -17778,70 +17820,100 @@ static void volume_dxt5_test(void) {{ 1.0f, -1.0f, 1.0f}, { 1.0f, 0.0f, 0.75f}}, {{ 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 0.75f}}, }; - static const DWORD expected_colors[] = {0x00ff0000, 0x0000ff00, 0x000000ff, 0x00ffffff}; - - window = create_window(); - d3d = Direct3DCreate9(D3D_SDK_VERSION); - ok(!!d3d, "Failed to create a D3D object.\n"); - if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, - D3DFMT_X8R8G8B8, 0, D3DRTYPE_VOLUMETEXTURE, D3DFMT_DXT5))) + static const DWORD expected_colors[3][8] = { { - skip("DXT5 volume textures are not supported, skipping test.\n"); - goto done; - } - if (!(device = create_device(d3d, window, window, TRUE))) + 0xFFFF0000, 0x00000000, 0xFF00FF00, 0xFF00FF00, + 0xFF0000FF, 0xFF0000FF, 0xFFFFFFFF, 0xFFFFFFFF, + }, { - skip("Failed to create a D3D device, skipping tests.\n"); - goto done; + 0xFFFF0000, 0xEEFF0000, 0xFF00FF00, 0xDD00FF00, + 0xFF0000FF, 0xCC0000FF, 0xFFFFFFFF, 0xBBFFFFFF, + }, + { + 0xFFFF0000, 0x00FF0000, 0xFF00FF00, 0xFF00FF00, + 0xFF0000FF, 0xFF0000FF, 0xFFFFFFFF, 0xFFFFFFFF } + }; + static const char *const dxtn[3] = {"DXT1", "DXT3", "DXT5"}; + static const unsigned int fmt[3] = {D3DFMT_DXT1, D3DFMT_DXT3, D3DFMT_DXT5};
- hr = IDirect3DDevice9_CreateVolumeTexture(device, 8, 4, 2, 1, 0, D3DFMT_DXT5, - D3DPOOL_MANAGED, &texture, NULL); - ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr); + for (x = 0; x < 3; x++) + { + window = create_window(); + d3d = Direct3DCreate9(D3D_SDK_VERSION); + ok(!!d3d, "Failed to create a D3D object.\n"); + if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_A8B8G8R8, 0, D3DRTYPE_VOLUMETEXTURE, fmt[x]))) + { + skip("%s volume textures are not supported, skipping test.\n", dxtn[x]); + continue; + } + if (!(device = create_device(d3d, window, window, TRUE))) + { + skip("Failed to create a D3D device, skipping tests.\n"); + continue; + }
- hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &box, NULL, 0); - ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr); - memcpy(box.pBits, texture_data, sizeof(texture_data)); - hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0); - ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr); + hr = IDirect3DDevice9_CreateVolumeTexture(device, 8, 4, 2, 1, 0, fmt[x], + D3DPOOL_MANAGED, &texture, NULL); + ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
- hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0)); - ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr); - hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture); - ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr); - hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr); - hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr); - hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE); - ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr); - hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - ok(SUCCEEDED(hr), "Failed to set mag filter, hr %#x.\n", hr); + hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &box, NULL, 0); + ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr); + switch (x) + { + case 0: + memcpy(box.pBits, dxt1_texture_data, sizeof(dxt1_texture_data)); + break; + case 1: + memcpy(box.pBits, dxt3_texture_data, sizeof(dxt3_texture_data)); + break; + case 2: + memcpy(box.pBits, dxt5_texture_data, sizeof(dxt5_texture_data)); + break; + } + hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0); + ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
- hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00ff00ff, 1.0f, 0); - ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr); - hr = IDirect3DDevice9_BeginScene(device); - ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); - hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[0], sizeof(*quads)); - ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); - hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[4], sizeof(*quads)); - ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); - hr = IDirect3DDevice9_EndScene(device); - ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0)); + ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture); + ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE); + ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + ok(SUCCEEDED(hr), "Failed to set mag filter, hr %#x.\n", hr);
- for (i = 0; i < 4; i++) - { - color = getPixelColor(device, 80 + 160 * i, 240); - ok (color_match(color, expected_colors[i], 1), - "Expected color 0x%08x, got 0x%08x, case %u.\n", expected_colors[i], color, i); + hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00ff00ff, 1.0f, 0); + ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr); + hr = IDirect3DDevice9_BeginScene(device); + ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); + hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[0], sizeof(*quads)); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[4], sizeof(*quads)); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + hr = IDirect3DDevice9_EndScene(device); + ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr); + + for (i = 0; i < 8; i++) + { + color = getAlphaPixelColor(device, 40 + 80 * i, 240); + ok (color_match(color, expected_colors[x][i], 1), + "Expected color 0x%08x, got 0x%08x, case %u.\n", expected_colors[x][i], color, i); + } + + hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); + ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); + IDirect3DVolumeTexture9_Release(texture); + + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); }
- hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); - ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); - IDirect3DVolumeTexture9_Release(texture); - refcount = IDirect3DDevice9_Release(device); - ok(!refcount, "Device has %u references left.\n", refcount); -done: IDirect3D9_Release(d3d); DestroyWindow(window); } @@ -24131,7 +24203,7 @@ START_TEST(visual) zenable_test(); fog_special_test(); volume_srgb_test(); - volume_dxt5_test(); + volume_dxtn_test(); add_dirty_rect_test(); multisampled_depth_buffer_test(); resz_test();
Hi,
While running your changed tests on Windows, 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=39289
Your paranoid android.
=== w1064 (64 bit visual) === visual.c:8645: Test failed: Got unexpected color 0x00007580 for quad 2 (different colors).