This patch adds the ability to decompress DXTn textures, and is meant to be used for DXTn 3D textures because they are not supported properly in drivers.
Signed-off-by: Connor McAdams conmanx360@gmail.com --- dlls/wined3d/texture.c | 54 +++++++- dlls/wined3d/utils.c | 271 ++++++++++++++++++++++++++++++++++++----- dlls/wined3d/wined3d_private.h | 4 + 3 files changed, 294 insertions(+), 35 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index c316906..5959048 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -567,6 +567,8 @@ static void wined3d_texture_allocate_gl_mutable_storage(struct wined3d_texture * unsigned int level, level_count, layer, layer_count; GLsizei width, height, depth; GLenum target; + GLint gl_format; + GLint gl_type;
level_count = texture->level_count; if (texture->target == GL_TEXTURE_1D_ARRAY || texture->target == GL_TEXTURE_2D_ARRAY) @@ -578,6 +580,18 @@ static void wined3d_texture_allocate_gl_mutable_storage(struct wined3d_texture * { target = wined3d_texture_get_sub_resource_target(texture, layer * level_count);
+ if (texture->resource.format_flags & WINED3DFMT_FLAG_DECOMPRESS) + { + gl_internal_format = GL_RGBA8; + gl_format = GL_BGRA; + gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; + } + else + { + gl_format = format->glFormat; + gl_type = format->glType; + } + for (level = 0; level < level_count; ++level) { width = wined3d_texture_get_level_pow2_width(texture, level); @@ -596,19 +610,19 @@ static void wined3d_texture_allocate_gl_mutable_storage(struct wined3d_texture * depth = wined3d_texture_get_level_depth(texture, level); GL_EXTCALL(glTexImage3D(target, level, gl_internal_format, width, height, target == GL_TEXTURE_2D_ARRAY ? texture->layer_count : depth, 0, - format->glFormat, format->glType, NULL)); + gl_format, gl_type, NULL)); checkGLcall("glTexImage3D"); } else if (target == GL_TEXTURE_1D) { gl_info->gl_ops.gl.p_glTexImage1D(target, level, gl_internal_format, - width, 0, format->glFormat, format->glType, NULL); + width, 0, gl_format, gl_type, NULL); } else { gl_info->gl_ops.gl.p_glTexImage2D(target, level, gl_internal_format, width, target == GL_TEXTURE_1D_ARRAY ? texture->layer_count : height, 0, - format->glFormat, format->glType, NULL); + gl_format, gl_type, NULL); checkGLcall("glTexImage2D"); } } @@ -624,6 +638,9 @@ static void wined3d_texture_allocate_gl_immutable_storage(struct wined3d_texture GLsizei height = wined3d_texture_get_level_pow2_height(texture, 0); GLsizei width = wined3d_texture_get_level_pow2_width(texture, 0);
+ if (texture->resource.format_flags & WINED3DFMT_FLAG_DECOMPRESS) + gl_internal_format = GL_RGBA8; + switch (texture->target) { case GL_TEXTURE_3D: @@ -1948,6 +1965,37 @@ void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int s bo.addr += src_box->left * format->byte_count; }
+ if (texture->resource.format_flags & WINED3DFMT_FLAG_DECOMPRESS) + { + unsigned int dst_row_pitch, dst_slice_pitch; + void *src_mem; + void (*decompress)(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, + unsigned int width, unsigned int height, unsigned int depth); + + decompress = format->decompress; + format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM, WINED3DUSAGE_TEXTURE); + + wined3d_format_calculate_pitch(format, 1, update_w, update_h, &dst_row_pitch, &dst_slice_pitch); + + if (!(converted_mem = heap_calloc(update_d, dst_slice_pitch))) + { + ERR("Failed to allocate upload buffer.\n"); + return; + } + src_mem = context_map_bo_address(context, &bo, src_slice_pitch, + GL_PIXEL_UNPACK_BUFFER, WINED3D_MAP_READ); + decompress(src_mem, converted_mem, src_row_pitch, src_slice_pitch, + dst_row_pitch, dst_slice_pitch, update_w, update_h, update_d); + context_unmap_bo_address(context, &bo, GL_PIXEL_UNPACK_BUFFER); + + bo.buffer_object = 0; + bo.addr = converted_mem; + src_row_pitch = dst_row_pitch; + src_slice_pitch = dst_slice_pitch; + texture->resource.format_flags &= ~WINED3DFMT_FLAG_BLOCKS; + } + if (format->upload) { unsigned int dst_row_pitch, dst_slice_pitch; diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 937c1bc..e6b0061 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -437,6 +437,9 @@ struct wined3d_format_texture_info void (*download)(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, unsigned int width, unsigned int height, unsigned int depth); + void (*decompress)(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, + unsigned int width, unsigned int height, unsigned int depth); };
static void convert_l4a4_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch, @@ -840,6 +843,206 @@ static void convert_s8_uint_d24_float(const BYTE *src, BYTE *dst, UINT src_row_p } }
+static void dxtn_decompress_block(const BYTE *src, BYTE *dst, UINT width, UINT height, UINT depth, + UINT x_pos, UINT y_pos, UINT z_pos, UINT dst_slice_pitch, UINT64 cur_block, UINT fmt, BYTE block_offset) +{ + UINT64 alpha_block, alpha_index, color_block, color_index; + const UINT64 *source; + DWORD *dest; + DWORD alpha_lookup; + DWORD bgra; + DWORD temp; + DWORD i, x, y; + WORD color[2]; + BYTE alpha_val, color_val; + BYTE alpha[8]; + BYTE r[4]; + BYTE g[4]; + BYTE b[4]; + + source = (const UINT64 *)(src + cur_block * block_offset); + if (fmt == WINED3DFMT_DXT1) + { + color_block = source[0]; + alpha_block = 0; + } + else + { + alpha_block = source[0]; + color_block = source[1]; + } + + 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 (fmt == WINED3DFMT_DXT3 || fmt == WINED3DFMT_DXT5 || 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; + } + } + else if (fmt == WINED3DFMT_DXT1 && 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; + } + + switch (fmt) + { + case WINED3DFMT_DXT1: + alpha_index = 0; + for (i = 0; i < ARRAY_SIZE(alpha); ++i) + alpha[i] = 255; + if (color[0] <= color[1]) + alpha[3] = 0; + break; + case WINED3DFMT_DXT3: + alpha_index = alpha_block; + for (i = 0; i < ARRAY_SIZE(alpha); ++i) + alpha[i] = 0; + break; + case WINED3DFMT_DXT5: + alpha_index = (alpha_block >> 16); + alpha[0] = alpha_block & 0xff; + alpha[1] = (alpha_block >> 8) & 0xff; + 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; + } + break; + default: + alpha_index = 0; + break; + } + + 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; + switch (fmt) + { + case WINED3DFMT_DXT1: + alpha_val = color_val; + break; + case WINED3DFMT_DXT3: + alpha_lookup = (alpha_index >> (y * 16)) & 0xffff; + alpha_val = (alpha_lookup >> (x * 4)) & 0xf; + temp = alpha_val * 255 + 8; + alpha[0] = (temp / 16 + temp) / 16; + alpha_val = 0; + break; + case WINED3DFMT_DXT5: + alpha_lookup = (alpha_index >> (y * 12)) & 0xfff; + alpha_val = (alpha_lookup >> (x * 3)) & 0x7; + break; + } + 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; + DWORD 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) + { + dxtn_decompress_block(src, dst, width, height, depth, x, y, z, dst_slice_pitch, current_block, WINED3DFMT_DXT5, 16); + current_block++; + } + } + } +} + +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; + DWORD 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) + { + dxtn_decompress_block(src, dst, width, height, depth, x, y, z, dst_slice_pitch, current_block, WINED3DFMT_DXT3, 16); + current_block++; + } + } + } +} + +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; + DWORD 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) + { + dxtn_decompress_block(src, dst, width, height, depth, x, y, z, dst_slice_pitch, current_block, WINED3DFMT_DXT1, 8); + 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, @@ -1066,7 +1269,7 @@ static const struct wined3d_format_texture_info format_texture_info[] = /* format id gl_internal gl_srgb_internal gl_rt_internal gl_format gl_type conv_byte_count flags - extension upload download */ + extension upload download decompress */ /* FourCC formats */ /* GL_APPLE_ycbcr_422 claims that its '2YUV' format, which is supported via the UNSIGNED_SHORT_8_8_REV_APPLE type * is equivalent to 'UYVY' format on Windows, and the 'YUVS' via UNSIGNED_SHORT_8_8_APPLE equates to 'YUY2'. The @@ -1118,42 +1321,42 @@ 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, NULL, NULL, 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, NULL, NULL, 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, NULL, NULL, 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, NULL, NULL, 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, NULL, NULL, 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 | WINED3DFMT_FLAG_COMPRESSED, - EXT_TEXTURE_COMPRESSION_S3TC, NULL}, + EXT_TEXTURE_COMPRESSION_S3TC, NULL, NULL, convert_dxt1_b8g8r8a8_unorm}, {WINED3DFMT_BC2_UNORM, 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_COMPRESSED, - EXT_TEXTURE_COMPRESSION_S3TC, NULL}, + EXT_TEXTURE_COMPRESSION_S3TC, NULL, NULL, convert_dxt3_b8g8r8a8_unorm}, {WINED3DFMT_BC3_UNORM, 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_COMPRESSED, - EXT_TEXTURE_COMPRESSION_S3TC, NULL}, + EXT_TEXTURE_COMPRESSION_S3TC, NULL, NULL, convert_dxt5_b8g8r8a8_unorm}, {WINED3DFMT_BC4_UNORM, GL_COMPRESSED_RED_RGTC1, GL_COMPRESSED_RED_RGTC1, 0, GL_RED, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING @@ -2928,6 +3131,7 @@ static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct win format->conv_byte_count = format_texture_info[i].conv_byte_count; format->upload = format_texture_info[i].upload; format->download = format_texture_info[i].download; + format->decompress = format_texture_info[i].decompress;
srgb_format = NULL; for (j = 0; j < ARRAY_SIZE(format_srgb_info); ++j) @@ -3394,29 +3598,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; - 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); - gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE; - idx = get_format_idx(WINED3DFMT_BC2_UNORM); - gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE; - idx = get_format_idx(WINED3DFMT_BC2_UNORM_SRGB); - gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE; - idx = get_format_idx(WINED3DFMT_BC3_UNORM); - gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE; - idx = get_format_idx(WINED3DFMT_BC3_UNORM_SRGB); - 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. */ /* Similarly with ATI1N / ATI2N and GL_ARB_texture_compression_rgtc. */ idx = get_format_idx(WINED3DFMT_ATI1N); gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE; @@ -3430,6 +3612,31 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_ gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE; idx = get_format_idx(WINED3DFMT_BC5_SNORM); gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE; + + /* This sets up which 3D textures can be decompressed through software. */ + idx = get_format_idx(WINED3DFMT_DXT1); + gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] |= WINED3DFMT_FLAG_DECOMPRESS; + idx = get_format_idx(WINED3DFMT_DXT2); + gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] |= WINED3DFMT_FLAG_DECOMPRESS; + idx = get_format_idx(WINED3DFMT_DXT3); + gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] |= WINED3DFMT_FLAG_DECOMPRESS; + idx = get_format_idx(WINED3DFMT_DXT4); + gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] |= WINED3DFMT_FLAG_DECOMPRESS; + idx = get_format_idx(WINED3DFMT_DXT5); + gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] |= WINED3DFMT_FLAG_DECOMPRESS; + idx = get_format_idx(WINED3DFMT_BC1_UNORM); + gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] |= WINED3DFMT_FLAG_DECOMPRESS; + idx = get_format_idx(WINED3DFMT_BC1_UNORM_SRGB); + gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] |= WINED3DFMT_FLAG_DECOMPRESS; + idx = get_format_idx(WINED3DFMT_BC2_UNORM); + gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] |= WINED3DFMT_FLAG_DECOMPRESS; + idx = get_format_idx(WINED3DFMT_BC2_UNORM_SRGB); + gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] |= WINED3DFMT_FLAG_DECOMPRESS; + idx = get_format_idx(WINED3DFMT_BC3_UNORM); + gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] |= WINED3DFMT_FLAG_DECOMPRESS; + idx = get_format_idx(WINED3DFMT_BC3_UNORM_SRGB); + gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] |= WINED3DFMT_FLAG_DECOMPRESS; + }
static unsigned int calculate_vertex_attribute_size(GLenum type, unsigned int component_count) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 9aa7081..b1d8b24 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4247,6 +4247,7 @@ extern enum wined3d_format_id pixelformat_for_depth(DWORD depth) DECLSPEC_HIDDEN #define WINED3DFMT_FLAG_BLOCKS_NO_VERIFY 0x00100000 #define WINED3DFMT_FLAG_INTEGER 0x00200000 #define WINED3DFMT_FLAG_GEN_MIPMAP 0x00400000 +#define WINED3DFMT_FLAG_DECOMPRESS 0x00800000
struct wined3d_rational { @@ -4306,6 +4307,9 @@ struct wined3d_format void (*download)(const BYTE *src, BYTE *dst, unsigned int src_row_pitch, unsigned int src_slice_pitch, unsigned int dst_row_pitch, unsigned dst_slice_pitch, unsigned int width, unsigned int height, unsigned int depth); + void (*decompress)(const BYTE *src, BYTE *dst, unsigned int src_row_pitch, unsigned int src_slice_pitch, + unsigned int dst_row_pitch, unsigned dst_slice_pitch, + unsigned int width, unsigned int height, unsigned int depth);
enum wined3d_format_id typeless_id; GLenum gl_view_class;
This patch adds tests to check if DXTn 3D volume textures are working properly. It tests DXT1, DXT3, and DXT5 formats.
Signed-off-by: Connor McAdams conmanx360@gmail.com --- dlls/d3d9/tests/visual.c | 183 +++++++++++++++++++++++++++++++---------------- 1 file changed, 123 insertions(+), 60 deletions(-)
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index b36c189..190ea1b 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -17741,26 +17741,73 @@ 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; + struct surface_readback rb; + IDirect3DSurface9 *rt; + DWORD i, x; ULONG refcount; DWORD color; HWND window; HRESULT hr;
- static const char texture_data[] = + static const BYTE dxt1_texture_data[] = + { + 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 BYTE dxt3_texture_data[] = + { + 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 BYTE 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 }; + static const DWORD dxt1_expected_colors[] = + { + 0xFFFF0000, 0x00000000, 0xFF00FF00, 0xFF00FF00, + 0xFF0000FF, 0xFF0000FF, 0xFFFFFFFF, 0xFFFFFFFF, + }; + static const DWORD dxt3_expected_colors[] = + { + 0xFFFF0000, 0xEEFF0000, 0xFF00FF00, 0xDD00FF00, + 0xFF0000FF, 0xCC0000FF, 0xFFFFFFFF, 0xBBFFFFFF, + }; + static const DWORD dxt5_expected_colors[] = + { + 0xFFFF0000, 0x00FF0000, 0xFF00FF00, 0xFF00FF00, + 0xFF0000FF, 0xFF0000FF, 0xFFFFFFFF, 0xFFFFFFFF + }; + + static const struct + { + const char *dxtn; + const BYTE *tex_data; + DWORD tex_size; + D3DFORMAT fmt; + const DWORD *expected_colors; + } + dxtn_tex[] = + { + {"DXT1", dxt1_texture_data, sizeof(dxt1_texture_data), D3DFMT_DXT1, dxt1_expected_colors}, + {"DXT3", dxt3_texture_data, sizeof(dxt3_texture_data), D3DFMT_DXT3, dxt3_expected_colors}, + {"DXT5", dxt5_texture_data, sizeof(dxt5_texture_data), D3DFMT_DXT5, dxt5_expected_colors}, + }; + static const struct { struct vec3 position; @@ -17778,70 +17825,86 @@ 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))) + for (x = 0; x < ARRAY_SIZE(dxtn_tex); ++x) { - skip("DXT5 volume textures are not supported, skipping test.\n"); - goto done; - } - if (!(device = create_device(d3d, window, window, TRUE))) - { - skip("Failed to create a D3D device, skipping tests.\n"); - goto done; - } + 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, dxtn_tex[x].fmt))) + { + skip("%s volume textures are not supported, skipping test.\n", dxtn_tex[x].dxtn); + continue; + } + if (!(device = create_device(d3d, window, window, TRUE))) + { + skip("Failed to create a D3D device, skipping tests.\n"); + continue; + }
- 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); + hr = IDirect3DDevice9_CreateVolumeTexture(device, 8, 4, 2, 1, 0, dxtn_tex[x].fmt, + D3DPOOL_MANAGED, &texture, NULL); + ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
- 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 = IDirect3DVolumeTexture9_LockBox(texture, 0, &box, NULL, 0); + ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr); + memcpy(box.pBits, dxtn_tex[x].tex_data, dxtn_tex[x].tex_size);
- 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_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 < ARRAY_SIZE(dxt1_expected_colors); ++i) + { + hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt); + if(FAILED(hr)) + { + trace("Can't get the render target, hr %#x.\n", hr); + color = 0x00000000; + } + else + { + get_rt_readback(rt, &rb); + color = get_readback_color(&rb, 40 + 80 * i, 240); + release_surface_readback(&rb); + IDirect3DSurface9_Release(rt); + } + ok (color_match(color, dxtn_tex[x].expected_colors[i], 1), + "Expected color 0x%08x, got 0x%08x, case %u.\n", dxtn_tex[x].expected_colors[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 +24194,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=39993
Your paranoid android.
=== w1064 (32 bit visual) === visual.c:8620: Test failed: Got unexpected color 0x00008080 for quad 2 (different colors).