[PATCH 1/2] wined3d: convert 3D DXTn textures
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(a)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; -- 2.7.4
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(a)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(); -- 2.7.4
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).
participants (2)
-
Connor McAdams -
Marvin