These patches implement the existing functionality of `load_texture_data()` using shared code.
-- v3: d3dx10: Exclusively use shared code in load_texture_data(). d3dx10: Exclusively use shared code to load DDS files in load_texture_data(). d3dx10: Add support for compressing BC4 and BC5 formats. d3dx10: Add support for decompressing BC4 and BC5 formats. d3dx10: Ignore alpha channel values for WICPixelFormat32bppBGR BMP images. d3dx10: Use shared code in load_texture_data() when possible.
From: Connor McAdams cmcadams@codeweavers.com
This optimzation helps us to more closely match the output of native d3dx's DXT compression, which helps with d3dx10 tests.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/stb_dxt.h | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/dlls/d3dx9_36/stb_dxt.h b/dlls/d3dx9_36/stb_dxt.h index c25f6b015da..2b40829deac 100644 --- a/dlls/d3dx9_36/stb_dxt.h +++ b/dlls/d3dx9_36/stb_dxt.h @@ -565,6 +565,16 @@ static void stb__CompressAlphaBlock(unsigned char *dest,unsigned char *src, int dest[1] = (unsigned char)mn; dest += 2;
+ /* + * Wine specific optimization to more closely match Windows behavior: If + * max is equal to minimum, just set all bits to 0 (which means the value + * is the value of max in this case). + */ + if (mx == mn) { + memset(dest, 0, 6); + return; + } + // determine bias and emit color indices // given the choice of mx/mn, these indices are optimal: // http://fgiesen.wordpress.com/2009/12/15/dxt5-alpha-block-index-determination...
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/tests/d3dx10.c | 2 +- dlls/d3dx10_43/texture.c | 113 +++++++++++++++++++++++++++++++++- dlls/d3dx9_36/d3dx_helpers.c | 17 +++-- dlls/d3dx9_36/d3dx_helpers.h | 4 ++ 4 files changed, 128 insertions(+), 8 deletions(-)
diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 9428787099f..3ec21ccc7bf 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -1579,7 +1579,7 @@ static void check_texture2d_data(ID3D10Texture2D *texture, const struct test_ima { line_match = !memcmp(expected_data + stride * i, (BYTE *)map.pData + map.RowPitch * i, stride); - todo_wine_if(is_block_compressed(image->expected_info.Format) + todo_wine_if(is_block_compressed(image->expected_info.Format) && image->data != test_dds_dxt5 && (image->expected_info.Width % 4 != 0 || image->expected_info.Height % 4 != 0)) ok_(__FILE__, line)(line_match, "Data mismatch for line %u, array slice %u.\n", i, array_slice); if (!line_match) diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index 9d0d6063a0b..7cab0cfc6f2 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -874,6 +874,93 @@ static HRESULT convert_image(IWICImagingFactory *factory, IWICBitmapFrameDecode return hr; }
+static HRESULT d3dx_load_texture_data(struct d3dx_image *image, D3DX10_IMAGE_LOAD_INFO *load_info, + const D3DX10_IMAGE_INFO *img_info, D3D10_SUBRESOURCE_DATA **resource_data) +{ + const struct pixel_format_desc *fmt_desc, *src_desc; + D3DX10_IMAGE_LOAD_INFO tmp_load_info = *load_info; + BYTE *res_data = NULL, *pixels_buffer; + uint32_t pixels_size, pixels_offset; + unsigned int i, j; + HRESULT hr = S_OK; + + if (img_info->ImageFileFormat == D3DX10_IFF_BMP) + return E_NOTIMPL; + + tmp_load_info.Format = img_info->Format; + fmt_desc = get_d3dx_pixel_format_info(d3dx_pixel_format_id_from_dxgi_format(tmp_load_info.Format)); + if (fmt_desc->format == D3DX_PIXEL_FORMAT_COUNT) + { + FIXME("Unknown DXGI format supplied, %#x.\n", tmp_load_info.Format); + return E_NOTIMPL; + } + + /* Potentially round up width/height to align with block size. */ + tmp_load_info.Width = (img_info->Width + fmt_desc->block_width - 1) & ~(fmt_desc->block_width - 1); + tmp_load_info.Height = (img_info->Height + fmt_desc->block_height - 1) & ~(fmt_desc->block_height - 1); + tmp_load_info.Depth = img_info->Depth; + tmp_load_info.MipLevels = img_info->MipLevels; + + pixels_size = d3dx_calculate_layer_pixels_size(fmt_desc->format, tmp_load_info.Width, tmp_load_info.Height, + tmp_load_info.Depth, tmp_load_info.MipLevels) * img_info->ArraySize; + pixels_offset = (sizeof(**resource_data) * tmp_load_info.MipLevels * img_info->ArraySize); + if (!(res_data = malloc(pixels_size + pixels_offset))) + return E_FAIL; + + pixels_buffer = res_data + pixels_offset; + *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data; + + src_desc = get_d3dx_pixel_format_info(image->format); + for (i = 0; i < img_info->ArraySize; ++i) + { + struct volume dst_size = { tmp_load_info.Width, tmp_load_info.Height, tmp_load_info.Depth }; + + for (j = 0; j < tmp_load_info.MipLevels; ++j) + { + const RECT unaligned_rect = { 0, 0, dst_size.width, dst_size.height }; + struct d3dx_pixels src_pixels, dst_pixels; + uint32_t dst_row_pitch, dst_slice_pitch; + + hr = d3dx_image_get_pixels(image, i, j, &src_pixels); + if (FAILED(hr)) + break; + + hr = d3dx_calculate_pixels_size(fmt_desc->format, dst_size.width, dst_size.height, &dst_row_pitch, + &dst_slice_pitch); + if (FAILED(hr)) + break; + + set_d3dx_pixels(&dst_pixels, pixels_buffer, dst_row_pitch, dst_slice_pitch, NULL, dst_size.width, + dst_size.height, dst_size.depth, &unaligned_rect); + + hr = d3dx_load_pixels_from_pixels(&dst_pixels, fmt_desc, &src_pixels, src_desc, D3DX10_FILTER_POINT, 0); + if (FAILED(hr)) + break; + + (*resource_data)[i * tmp_load_info.MipLevels + j].pSysMem = pixels_buffer; + (*resource_data)[i * tmp_load_info.MipLevels + j].SysMemPitch = dst_row_pitch; + (*resource_data)[i * tmp_load_info.MipLevels + j].SysMemSlicePitch = dst_slice_pitch; + + pixels_buffer += dst_slice_pitch * dst_size.depth; + d3dx_get_next_mip_level_size(&dst_size); + } + } + + if (FAILED(hr)) + { + *resource_data = NULL; + free(res_data); + return hr; + } + + *load_info = tmp_load_info; + load_info->Usage = D3D10_USAGE_DEFAULT; + load_info->BindFlags = D3D10_BIND_SHADER_RESOURCE; + load_info->MiscFlags = img_info->MiscFlags; + + return S_OK; +} + HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO *load_info, D3D10_SUBRESOURCE_DATA **resource_data) { @@ -886,9 +973,13 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO BYTE *res_data = NULL, *buffer; D3DX10_IMAGE_INFO img_info; IWICStream *stream = NULL; + struct d3dx_image image; const GUID *dst_format; HRESULT hr;
+ if (!data || !size) + return E_FAIL; + if (load_info->Width != D3DX10_DEFAULT) FIXME("load_info->Width is ignored.\n"); if (load_info->Height != D3DX10_DEFAULT) @@ -916,15 +1007,32 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO if (load_info->pSrcInfo) FIXME("load_info->pSrcInfo is ignored.\n");
- if (FAILED(D3DX10GetImageInfoFromMemory(data, size, NULL, &img_info, NULL))) + hr = d3dx_image_init(data, size, &image, 0, D3DX_IMAGE_SUPPORT_DXT10); + if (FAILED(hr)) return E_FAIL; + + hr = d3dx10_image_info_from_d3dx_image(&img_info, &image); + if (FAILED(hr)) + { + WARN("Invalid or unsupported image file, hr %#lx.\n", hr); + hr = E_FAIL; + goto end; + } + if ((!(img_info.MiscFlags & D3D10_RESOURCE_MISC_TEXTURECUBE) || img_info.ArraySize != 6) && img_info.ArraySize != 1) { FIXME("img_info.ArraySize = %u not supported.\n", img_info.ArraySize); - return E_NOTIMPL; + hr = E_NOTIMPL; + goto end; }
+ if (SUCCEEDED(hr = d3dx_load_texture_data(&image, load_info, &img_info, resource_data))) + { + TRACE("Successfully used shared code to load texture data.\n"); + res_data = NULL; + goto end; + }
if (FAILED(hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory))) goto end; @@ -1067,6 +1175,7 @@ end: IWICDdsDecoder_Release(dds_decoder); if (dds_frame) IWICDdsFrameDecode_Release(dds_frame); + d3dx_image_cleanup(&image); free(res_data); if (frame) IWICBitmapFrameDecode_Release(frame); diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c index 57ca8f1c0a7..20a316c3420 100644 --- a/dlls/d3dx9_36/d3dx_helpers.c +++ b/dlls/d3dx9_36/d3dx_helpers.c @@ -383,7 +383,7 @@ static HRESULT dds_pixel_format_from_d3dx_pixel_format_id(struct dds_pixel_forma return D3D_OK; }
-static enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(DXGI_FORMAT format) +enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(uint32_t format) { switch (format) { @@ -423,7 +423,7 @@ static enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(DXGI_FORM } }
-static void d3dx_get_next_mip_level_size(struct volume *size) +void d3dx_get_next_mip_level_size(struct volume *size) { size->width = max(size->width / 2, 1); size->height = max(size->height / 2, 1); @@ -437,7 +437,7 @@ static const char *debug_volume(const struct volume *volume) return wine_dbg_sprintf("(%ux%ux%u)", volume->width, volume->height, volume->depth); }
-static HRESULT d3dx_calculate_pixels_size(enum d3dx_pixel_format_id format, uint32_t width, uint32_t height, +HRESULT d3dx_calculate_pixels_size(enum d3dx_pixel_format_id format, uint32_t width, uint32_t height, uint32_t *pitch, uint32_t *size) { const struct pixel_format_desc *format_desc = get_d3dx_pixel_format_info(format); @@ -1188,9 +1188,16 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src expected_src_data_size = (image->layer_pitch * image->layer_count) + header_size; if (src_data_size < expected_src_data_size) { + const uint32_t dxt10_info_only_flags = D3DX_IMAGE_INFO_ONLY | D3DX_IMAGE_SUPPORT_DXT10; + WARN("File is too short %u, expected at least %u bytes.\n", src_data_size, expected_src_data_size); - /* D3DX10/D3DX11 do not validate the size of the pixels, only the header. */ - if (!(flags & D3DX_IMAGE_SUPPORT_DXT10)) + /* + * D3DX10/D3DX11 do not validate the size of the pixels, only the header. + * This is safe if we're only getting image info, but we should avoid + * matching native behavior here when loading image data until we have + * a reason to do otherwise. + */ + if ((flags & dxt10_info_only_flags) != dxt10_info_only_flags) return D3DXERR_INVALIDDATA; }
diff --git a/dlls/d3dx9_36/d3dx_helpers.h b/dlls/d3dx9_36/d3dx_helpers.h index a840f99b46e..0126dcd3f1b 100644 --- a/dlls/d3dx9_36/d3dx_helpers.h +++ b/dlls/d3dx9_36/d3dx_helpers.h @@ -399,6 +399,10 @@ void format_to_d3dx_color(const struct pixel_format_desc *format, const BYTE *sr struct d3dx_color *dst); void format_from_d3dx_color(const struct pixel_format_desc *format, const struct d3dx_color *src, BYTE *dst);
+enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(uint32_t format); +void d3dx_get_next_mip_level_size(struct volume *size); +HRESULT d3dx_calculate_pixels_size(enum d3dx_pixel_format_id format, uint32_t width, uint32_t height, + uint32_t *pitch, uint32_t *size); uint32_t d3dx_calculate_layer_pixels_size(enum d3dx_pixel_format_id format, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels); HRESULT d3dx_init_dds_header(struct dds_header *header, enum d3dx_resource_type resource_type,
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/texture.c | 3 --- dlls/d3dx9_36/d3dx_helpers.c | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index 7cab0cfc6f2..743472ee97a 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -884,9 +884,6 @@ static HRESULT d3dx_load_texture_data(struct d3dx_image *image, D3DX10_IMAGE_LOA unsigned int i, j; HRESULT hr = S_OK;
- if (img_info->ImageFileFormat == D3DX10_IFF_BMP) - return E_NOTIMPL; - tmp_load_info.Format = img_info->Format; fmt_desc = get_d3dx_pixel_format_info(d3dx_pixel_format_id_from_dxgi_format(tmp_load_info.Format)); if (fmt_desc->format == D3DX_PIXEL_FORMAT_COUNT) diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c index 20a316c3420..4ece472d39f 100644 --- a/dlls/d3dx9_36/d3dx_helpers.c +++ b/dlls/d3dx9_36/d3dx_helpers.c @@ -1500,7 +1500,8 @@ static HRESULT d3dx_initialize_image_from_wic(const void *src_data, uint32_t src break; }
- if (image_is_argb(bitmap_frame, image)) + /* D3DX10/D3DX11 ignore alpha channels in X8 bitmaps. */ + if (!(flags & D3DX_IMAGE_SUPPORT_DXT10) && image_is_argb(bitmap_frame, image)) image->format = D3DX_PIXEL_FORMAT_B8G8R8A8_UNORM;
if (!(flags & D3DX_IMAGE_INFO_ONLY))
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/texture.c | 1 + dlls/d3dx9_36/bcdec.h | 6 +++--- dlls/d3dx9_36/d3dx_helpers.c | 21 +++++++++++++++++++++ dlls/d3dx9_36/d3dx_helpers.h | 1 + 4 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index 743472ee97a..88ecabe069f 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -114,6 +114,7 @@ static DXGI_FORMAT dxgi_format_from_d3dx_pixel_format_id(enum d3dx_pixel_format_ case D3DX_PIXEL_FORMAT_R10G10B10A2_UNORM: return DXGI_FORMAT_R10G10B10A2_UNORM; case D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM: return DXGI_FORMAT_R16G16B16A16_UNORM; case D3DX_PIXEL_FORMAT_R8_UNORM: return DXGI_FORMAT_R8_UNORM; + case D3DX_PIXEL_FORMAT_R8_SNORM: return DXGI_FORMAT_R8_SNORM; case D3DX_PIXEL_FORMAT_R8G8_UNORM: return DXGI_FORMAT_R8G8_UNORM; case D3DX_PIXEL_FORMAT_R16_UNORM: return DXGI_FORMAT_R16_UNORM; case D3DX_PIXEL_FORMAT_R16G16_UNORM: return DXGI_FORMAT_R16G16_UNORM; diff --git a/dlls/d3dx9_36/bcdec.h b/dlls/d3dx9_36/bcdec.h index 5ead984c466..1b57a454926 100644 --- a/dlls/d3dx9_36/bcdec.h +++ b/dlls/d3dx9_36/bcdec.h @@ -90,9 +90,9 @@ BCDECDEF void bcdec_bc1(const void* compressedBlock, void* decompressedBlock, int destinationPitch); BCDECDEF void bcdec_bc2(const void* compressedBlock, void* decompressedBlock, int destinationPitch); BCDECDEF void bcdec_bc3(const void* compressedBlock, void* decompressedBlock, int destinationPitch); -#ifdef WINE_UNUSED /* unused for now in Wine */ BCDECDEF void bcdec_bc4(const void* compressedBlock, void* decompressedBlock, int destinationPitch); BCDECDEF void bcdec_bc5(const void* compressedBlock, void* decompressedBlock, int destinationPitch); +#ifdef WINE_UNUSED /* unused for now in Wine */ BCDECDEF void bcdec_bc6h_float(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned); BCDECDEF void bcdec_bc6h_half(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned); BCDECDEF void bcdec_bc7(const void* compressedBlock, void* decompressedBlock, int destinationPitch); @@ -275,8 +275,6 @@ BCDECDEF void bcdec_bc3(const void* compressedBlock, void* decompressedBlock, in bcdec__smooth_alpha_block(compressedBlock, ((char*)decompressedBlock) + 3, destinationPitch, 4); }
-#ifdef WINE_UNUSED /* unused for now in Wine */ - BCDECDEF void bcdec_bc4(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { bcdec__smooth_alpha_block(compressedBlock, decompressedBlock, destinationPitch, 1); } @@ -286,6 +284,8 @@ BCDECDEF void bcdec_bc5(const void* compressedBlock, void* decompressedBlock, in bcdec__smooth_alpha_block(((char*)compressedBlock) + 8, ((char*)decompressedBlock) + 1, destinationPitch, 2); }
+#ifdef WINE_UNUSED /* unused for now in Wine */ + /* http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend */ static int bcdec__extend_sign(int val, int bits) { return (val << (32 - bits)) >> (32 - bits); diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c index 4ece472d39f..ae41c370013 100644 --- a/dlls/d3dx9_36/d3dx_helpers.c +++ b/dlls/d3dx9_36/d3dx_helpers.c @@ -81,6 +81,7 @@ static const struct pixel_format_desc formats[] = {D3DX_PIXEL_FORMAT_R16G16B16_UNORM, { 0, 16, 16, 16}, { 0, 0, 16, 32}, 6, 1, 1, 6, CTYPE_EMPTY, CTYPE_UNORM, FMT_FLAG_INTERNAL}, {D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM, {16, 16, 16, 16}, {48, 0, 16, 32}, 8, 1, 1, 8, CTYPE_UNORM, CTYPE_UNORM, 0 }, {D3DX_PIXEL_FORMAT_R8_UNORM, { 0, 8, 0, 0}, { 0, 0, 0, 0}, 1, 1, 1, 1, CTYPE_EMPTY, CTYPE_UNORM, FMT_FLAG_DXGI}, + {D3DX_PIXEL_FORMAT_R8_SNORM, { 0, 8, 0, 0}, { 0, 0, 0, 0}, 1, 1, 1, 1, CTYPE_EMPTY, CTYPE_SNORM, FMT_FLAG_DXGI}, {D3DX_PIXEL_FORMAT_R8G8_UNORM, { 0, 8, 8, 0}, { 0, 0, 8, 0}, 2, 1, 1, 2, CTYPE_EMPTY, CTYPE_UNORM, FMT_FLAG_DXGI}, {D3DX_PIXEL_FORMAT_R16_UNORM, { 0, 16, 0, 0}, { 0, 0, 0, 0}, 2, 1, 1, 2, CTYPE_EMPTY, CTYPE_UNORM, FMT_FLAG_DXGI}, {D3DX_PIXEL_FORMAT_R16G16_UNORM, { 0, 16, 16, 0}, { 0, 0, 16, 0}, 4, 1, 1, 4, CTYPE_EMPTY, CTYPE_UNORM, 0 }, @@ -396,6 +397,7 @@ enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(uint32_t format) case DXGI_FORMAT_R10G10B10A2_UNORM: return D3DX_PIXEL_FORMAT_R10G10B10A2_UNORM; case DXGI_FORMAT_R16G16B16A16_UNORM: return D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM; case DXGI_FORMAT_R8_UNORM: return D3DX_PIXEL_FORMAT_R8_UNORM; + case DXGI_FORMAT_R8_SNORM: return D3DX_PIXEL_FORMAT_R8_SNORM; case DXGI_FORMAT_R8G8_UNORM: return D3DX_PIXEL_FORMAT_R8G8_UNORM; case DXGI_FORMAT_R16_UNORM: return D3DX_PIXEL_FORMAT_R16_UNORM; case DXGI_FORMAT_R16G16_UNORM: return D3DX_PIXEL_FORMAT_R16G16_UNORM; @@ -2582,6 +2584,25 @@ static HRESULT d3dx_pixels_decompress(struct d3dx_pixels *pixels, const struct p decompress_bcn_block = bcdec_bc3; break;
+ case D3DX_PIXEL_FORMAT_BC4_UNORM: + case D3DX_PIXEL_FORMAT_BC4_SNORM: + if (desc->rgb_type == CTYPE_UNORM) + uncompressed_desc = get_d3dx_pixel_format_info(D3DX_PIXEL_FORMAT_R8_UNORM); + else + uncompressed_desc = get_d3dx_pixel_format_info(D3DX_PIXEL_FORMAT_R8_SNORM); + decompress_bcn_block = bcdec_bc4; + break; + + case D3DX_PIXEL_FORMAT_BC5_UNORM: + case D3DX_PIXEL_FORMAT_BC5_SNORM: + if (desc->rgb_type == CTYPE_UNORM) + uncompressed_desc = get_d3dx_pixel_format_info(D3DX_PIXEL_FORMAT_R8G8_UNORM); + else + uncompressed_desc = get_d3dx_pixel_format_info(D3DX_PIXEL_FORMAT_R8G8_SNORM); + decompress_bcn_block = bcdec_bc5; + break; + + default: FIXME("Unexpected compressed texture format %u.\n", desc->format); return E_NOTIMPL; diff --git a/dlls/d3dx9_36/d3dx_helpers.h b/dlls/d3dx9_36/d3dx_helpers.h index 0126dcd3f1b..42b40c1c279 100644 --- a/dlls/d3dx9_36/d3dx_helpers.h +++ b/dlls/d3dx9_36/d3dx_helpers.h @@ -188,6 +188,7 @@ enum d3dx_pixel_format_id D3DX_PIXEL_FORMAT_R16G16B16_UNORM, D3DX_PIXEL_FORMAT_R16G16B16A16_UNORM, D3DX_PIXEL_FORMAT_R8_UNORM, + D3DX_PIXEL_FORMAT_R8_SNORM, D3DX_PIXEL_FORMAT_R8G8_UNORM, D3DX_PIXEL_FORMAT_R16_UNORM, D3DX_PIXEL_FORMAT_R16G16_UNORM,
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx_helpers.c | 26 ++++++++++++++++++++++++++ dlls/d3dx9_36/stb_dxt.h | 5 ----- 2 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c index ae41c370013..e9a97578ac5 100644 --- a/dlls/d3dx9_36/d3dx_helpers.c +++ b/dlls/d3dx9_36/d3dx_helpers.c @@ -2818,6 +2818,16 @@ static void d3dx_compress_block(enum d3dx_pixel_format_id fmt, uint8_t *block_bu stb_compress_dxt_block(dst_buf, block_buf, TRUE, 0); break;
+ case D3DX_PIXEL_FORMAT_BC4_UNORM: + case D3DX_PIXEL_FORMAT_BC4_SNORM: + stb_compress_bc4_block(dst_buf, block_buf); + break; + + case D3DX_PIXEL_FORMAT_BC5_UNORM: + case D3DX_PIXEL_FORMAT_BC5_SNORM: + stb_compress_bc5_block(dst_buf, block_buf); + break; + default: assert(0); break; @@ -2847,6 +2857,22 @@ static HRESULT d3dx_pixels_compress(struct d3dx_pixels *src_pixels, assert(src_desc->format == D3DX_PIXEL_FORMAT_R8G8B8A8_UNORM); break;
+ case D3DX_PIXEL_FORMAT_BC4_UNORM: + assert(src_desc->format == D3DX_PIXEL_FORMAT_R8_UNORM); + break; + + case D3DX_PIXEL_FORMAT_BC4_SNORM: + assert(src_desc->format == D3DX_PIXEL_FORMAT_R8_SNORM); + break; + + case D3DX_PIXEL_FORMAT_BC5_UNORM: + assert(src_desc->format == D3DX_PIXEL_FORMAT_R8G8_UNORM); + break; + + case D3DX_PIXEL_FORMAT_BC5_SNORM: + assert(src_desc->format == D3DX_PIXEL_FORMAT_R8G8_SNORM); + break; + default: FIXME("Unexpected compressed texture format %u.\n", dst_desc->format); return E_NOTIMPL; diff --git a/dlls/d3dx9_36/stb_dxt.h b/dlls/d3dx9_36/stb_dxt.h index 2b40829deac..46375273e64 100644 --- a/dlls/d3dx9_36/stb_dxt.h +++ b/dlls/d3dx9_36/stb_dxt.h @@ -56,10 +56,8 @@ extern "C" { #define STB_DXT_HIGHQUAL 2 // high quality mode, does two refinement steps instead of 1. ~30-40% slower.
STBDDEF void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src_rgba_four_bytes_per_pixel, int alpha, int mode); -#ifdef WINE_UNUSED /* unused for now in Wine */ STBDDEF void stb_compress_bc4_block(unsigned char *dest, const unsigned char *src_r_one_byte_per_pixel); STBDDEF void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src_rg_two_byte_per_pixel); -#endif /* WINE_UNUSED */
#define STB_COMPRESS_DXT_BLOCK
@@ -626,8 +624,6 @@ void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int a stb__CompressColorBlock(dest,(unsigned char*) src,mode); }
-#ifdef WINE_UNUSED /* unused for now in Wine */ - void stb_compress_bc4_block(unsigned char *dest, const unsigned char *src) { stb__CompressAlphaBlock(dest,(unsigned char*) src, 1); @@ -638,7 +634,6 @@ void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src) stb__CompressAlphaBlock(dest,(unsigned char*) src,2); stb__CompressAlphaBlock(dest + 8,(unsigned char*) src+1,2); } -#endif /* WINE_UNUSED */
#endif // STB_DXT_IMPLEMENTATION
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/texture.c | 170 ++++++----------------------------- dlls/d3dx9_36/d3dx_helpers.c | 4 + 2 files changed, 30 insertions(+), 144 deletions(-)
diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index 88ecabe069f..0be79fb922d 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -806,32 +806,6 @@ void init_load_info(const D3DX10_IMAGE_LOAD_INFO *load_info, D3DX10_IMAGE_LOAD_I out->pSrcInfo = NULL; }
-static HRESULT dds_get_frame_info(IWICDdsFrameDecode *frame, const D3DX10_IMAGE_INFO *img_info, - WICDdsFormatInfo *format_info, unsigned int *stride, unsigned int *frame_size) -{ - unsigned int width, height; - HRESULT hr; - - if (FAILED(hr = IWICDdsFrameDecode_GetFormatInfo(frame, format_info))) - return hr; - if (FAILED(hr = IWICDdsFrameDecode_GetSizeInBlocks(frame, &width, &height))) - return hr; - - if (img_info->Format == format_info->DxgiFormat) - { - *stride = width * format_info->BytesPerBlock; - *frame_size = *stride * height; - } - else - { - width *= format_info->BlockWidth; - height *= format_info->BlockHeight; - *stride = (width * get_bpp_from_format(img_info->Format) + 7) / 8; - *frame_size = *stride * height; - } - return S_OK; -} - static HRESULT convert_image(IWICImagingFactory *factory, IWICBitmapFrameDecode *frame, const GUID *dst_format, unsigned int stride, unsigned int frame_size, BYTE *buffer) { @@ -962,12 +936,10 @@ static HRESULT d3dx_load_texture_data(struct d3dx_image *image, D3DX10_IMAGE_LOA HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO *load_info, D3D10_SUBRESOURCE_DATA **resource_data) { - unsigned int stride, frame_size, i, j; - IWICDdsFrameDecode *dds_frame = NULL; IWICBitmapFrameDecode *frame = NULL; IWICImagingFactory *factory = NULL; - IWICDdsDecoder *dds_decoder = NULL; IWICBitmapDecoder *decoder = NULL; + unsigned int stride, frame_size; BYTE *res_data = NULL, *buffer; D3DX10_IMAGE_INFO img_info; IWICStream *stream = NULL; @@ -1031,6 +1003,10 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO res_data = NULL; goto end; } + else if (img_info.ImageFileFormat == D3DX10_IFF_DDS) + { + goto end; + }
if (FAILED(hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory))) goto end; @@ -1040,122 +1016,32 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO goto end; if (FAILED(hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream *)stream, NULL, 0, &decoder))) goto end; + if (FAILED(hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame))) + goto end;
- if (img_info.ImageFileFormat == D3DX10_IFF_DDS) - { - WICDdsFormatInfo format_info; - size_t size = 0; - - if (FAILED(hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICDdsDecoder, (void **)&dds_decoder))) - goto end; - - for (i = 0; i < img_info.ArraySize; ++i) - { - for (j = 0; j < img_info.MipLevels; ++j) - { - if (FAILED(hr = IWICDdsDecoder_GetFrame(dds_decoder, i, j, 0, &frame))) - goto end; - if (FAILED(hr = IWICBitmapFrameDecode_QueryInterface(frame, - &IID_IWICDdsFrameDecode, (void **)&dds_frame))) - goto end; - if (FAILED(hr = dds_get_frame_info(dds_frame, &img_info, &format_info, &stride, &frame_size))) - goto end; - - if (!i && !j) - { - img_info.Width = (img_info.Width + format_info.BlockWidth - 1) & ~(format_info.BlockWidth - 1); - img_info.Height = (img_info.Height + format_info.BlockHeight - 1) & ~(format_info.BlockHeight - 1); - } - - size += sizeof(**resource_data) + frame_size; - - IWICDdsFrameDecode_Release(dds_frame); - dds_frame = NULL; - IWICBitmapFrameDecode_Release(frame); - frame = NULL; - } - } - - if (!(res_data = malloc(size))) - { - hr = E_FAIL; - goto end; - } - *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data; + stride = (img_info.Width * get_bpp_from_format(img_info.Format) + 7) / 8; + frame_size = stride * img_info.Height;
- size = 0; - for (i = 0; i < img_info.ArraySize; ++i) - { - for (j = 0; j < img_info.MipLevels; ++j) - { - if (FAILED(hr = IWICDdsDecoder_GetFrame(dds_decoder, i, j, 0, &frame))) - goto end; - if (FAILED(hr = IWICBitmapFrameDecode_QueryInterface(frame, - &IID_IWICDdsFrameDecode, (void **)&dds_frame))) - goto end; - if (FAILED(hr = dds_get_frame_info(dds_frame, &img_info, &format_info, &stride, &frame_size))) - goto end; - - buffer = res_data + sizeof(**resource_data) * img_info.ArraySize * img_info.MipLevels + size; - size += frame_size; - - if (img_info.Format == format_info.DxgiFormat) - { - if (FAILED(hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, stride, frame_size, buffer))) - goto end; - } - else - { - if (!(dst_format = dxgi_format_to_wic_guid(img_info.Format))) - { - hr = E_FAIL; - FIXME("Unsupported DXGI format %#x.\n", img_info.Format); - goto end; - } - if (FAILED(hr = convert_image(factory, frame, dst_format, stride, frame_size, buffer))) - goto end; - } - - IWICDdsFrameDecode_Release(dds_frame); - dds_frame = NULL; - IWICBitmapFrameDecode_Release(frame); - frame = NULL; - - (*resource_data)[i * img_info.MipLevels + j].pSysMem = buffer; - (*resource_data)[i * img_info.MipLevels + j].SysMemPitch = stride; - (*resource_data)[i * img_info.MipLevels + j].SysMemSlicePitch = frame_size; - } - } - } - else + if (!(res_data = malloc(sizeof(**resource_data) + frame_size))) { - if (FAILED(hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame))) - goto end; - - stride = (img_info.Width * get_bpp_from_format(img_info.Format) + 7) / 8; - frame_size = stride * img_info.Height; - - if (!(res_data = malloc(sizeof(**resource_data) + frame_size))) - { - hr = E_FAIL; - goto end; - } - buffer = res_data + sizeof(**resource_data); - - if (!(dst_format = dxgi_format_to_wic_guid(img_info.Format))) - { - hr = E_FAIL; - FIXME("Unsupported DXGI format %#x.\n", img_info.Format); - goto end; - } - if (FAILED(hr = convert_image(factory, frame, dst_format, stride, frame_size, buffer))) - goto end; + hr = E_FAIL; + goto end; + } + buffer = res_data + sizeof(**resource_data);
- *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data; - (*resource_data)->pSysMem = buffer; - (*resource_data)->SysMemPitch = stride; - (*resource_data)->SysMemSlicePitch = frame_size; + if (!(dst_format = dxgi_format_to_wic_guid(img_info.Format))) + { + hr = E_FAIL; + FIXME("Unsupported DXGI format %#x.\n", img_info.Format); + goto end; } + if (FAILED(hr = convert_image(factory, frame, dst_format, stride, frame_size, buffer))) + goto end; + + *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data; + (*resource_data)->pSysMem = buffer; + (*resource_data)->SysMemPitch = stride; + (*resource_data)->SysMemSlicePitch = frame_size;
load_info->Width = img_info.Width; load_info->Height = img_info.Height; @@ -1169,10 +1055,6 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO hr = S_OK;
end: - if (dds_decoder) - IWICDdsDecoder_Release(dds_decoder); - if (dds_frame) - IWICDdsFrameDecode_Release(dds_frame); d3dx_image_cleanup(&image); free(res_data); if (frame) diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c index e9a97578ac5..83c9befb08b 100644 --- a/dlls/d3dx9_36/d3dx_helpers.c +++ b/dlls/d3dx9_36/d3dx_helpers.c @@ -414,6 +414,10 @@ enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dxgi_format(uint32_t format) case DXGI_FORMAT_BC1_UNORM: return D3DX_PIXEL_FORMAT_BC1_UNORM; case DXGI_FORMAT_BC2_UNORM: return D3DX_PIXEL_FORMAT_BC2_UNORM; case DXGI_FORMAT_BC3_UNORM: return D3DX_PIXEL_FORMAT_BC3_UNORM; + case DXGI_FORMAT_BC4_UNORM: return D3DX_PIXEL_FORMAT_BC4_UNORM; + case DXGI_FORMAT_BC4_SNORM: return D3DX_PIXEL_FORMAT_BC4_SNORM; + case DXGI_FORMAT_BC5_UNORM: return D3DX_PIXEL_FORMAT_BC5_UNORM; + case DXGI_FORMAT_BC5_SNORM: return D3DX_PIXEL_FORMAT_BC5_SNORM; case DXGI_FORMAT_R8G8B8A8_SNORM: return D3DX_PIXEL_FORMAT_R8G8B8A8_SNORM; case DXGI_FORMAT_R8G8_SNORM: return D3DX_PIXEL_FORMAT_R8G8_SNORM; case DXGI_FORMAT_R16G16_SNORM: return D3DX_PIXEL_FORMAT_R16G16_SNORM;
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/texture.c | 413 ++++++--------------------------------- 1 file changed, 59 insertions(+), 354 deletions(-)
diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index 0be79fb922d..85459cc9a56 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -22,13 +22,10 @@
#include "d3d10_1.h" #include "d3dx10.h" -#include "wincodec.h" #include "dxhelpers.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
-HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT sdk_version, IWICImagingFactory **imaging_factory); - /* * These are mappings from legacy DDS header formats to DXGI formats. Some * don't map to a DXGI_FORMAT at all, and some only map to the default format. @@ -173,179 +170,6 @@ static D3DX10_IMAGE_FILE_FORMAT d3dx10_image_file_format_from_d3dx_image_file_fo } }
-static const struct -{ - const GUID *wic_guid; - DXGI_FORMAT dxgi_format; -} -wic_pixel_formats[] = -{ - { &GUID_WICPixelFormatBlackWhite, DXGI_FORMAT_R1_UNORM }, - { &GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM }, - { &GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM }, - { &GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM }, - { &GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT }, - { &GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT }, - { &GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM }, - { &GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM }, - { &GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM }, - { &GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM }, - { &GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM }, - { &GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM }, - { &GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, - { &GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM }, - { &GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT }, - { &GUID_WICPixelFormat96bppRGBFloat, DXGI_FORMAT_R32G32B32_FLOAT }, - { &GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT } -}; - -static const GUID *dxgi_format_to_wic_guid(DXGI_FORMAT format) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(wic_pixel_formats); ++i) - { - if (wic_pixel_formats[i].dxgi_format == format) - return wic_pixel_formats[i].wic_guid; - } - - return NULL; -} - -static unsigned int get_bpp_from_format(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_R32G32B32A32_TYPELESS: - case DXGI_FORMAT_R32G32B32A32_FLOAT: - case DXGI_FORMAT_R32G32B32A32_UINT: - case DXGI_FORMAT_R32G32B32A32_SINT: - return 128; - case DXGI_FORMAT_R32G32B32_TYPELESS: - case DXGI_FORMAT_R32G32B32_FLOAT: - case DXGI_FORMAT_R32G32B32_UINT: - case DXGI_FORMAT_R32G32B32_SINT: - return 96; - case DXGI_FORMAT_R16G16B16A16_TYPELESS: - case DXGI_FORMAT_R16G16B16A16_FLOAT: - case DXGI_FORMAT_R16G16B16A16_UNORM: - case DXGI_FORMAT_R16G16B16A16_UINT: - case DXGI_FORMAT_R16G16B16A16_SNORM: - case DXGI_FORMAT_R16G16B16A16_SINT: - case DXGI_FORMAT_R32G32_TYPELESS: - case DXGI_FORMAT_R32G32_FLOAT: - case DXGI_FORMAT_R32G32_UINT: - case DXGI_FORMAT_R32G32_SINT: - case DXGI_FORMAT_R32G8X24_TYPELESS: - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: - case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: - case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: - case DXGI_FORMAT_Y416: - case DXGI_FORMAT_Y210: - case DXGI_FORMAT_Y216: - return 64; - case DXGI_FORMAT_R10G10B10A2_TYPELESS: - case DXGI_FORMAT_R10G10B10A2_UNORM: - case DXGI_FORMAT_R10G10B10A2_UINT: - case DXGI_FORMAT_R11G11B10_FLOAT: - case DXGI_FORMAT_R8G8B8A8_TYPELESS: - case DXGI_FORMAT_R8G8B8A8_UNORM: - case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - case DXGI_FORMAT_R8G8B8A8_UINT: - case DXGI_FORMAT_R8G8B8A8_SNORM: - case DXGI_FORMAT_R8G8B8A8_SINT: - case DXGI_FORMAT_R16G16_TYPELESS: - case DXGI_FORMAT_R16G16_FLOAT: - case DXGI_FORMAT_R16G16_UNORM: - case DXGI_FORMAT_R16G16_UINT: - case DXGI_FORMAT_R16G16_SNORM: - case DXGI_FORMAT_R16G16_SINT: - case DXGI_FORMAT_R32_TYPELESS: - case DXGI_FORMAT_D32_FLOAT: - case DXGI_FORMAT_R32_FLOAT: - case DXGI_FORMAT_R32_UINT: - case DXGI_FORMAT_R32_SINT: - case DXGI_FORMAT_R24G8_TYPELESS: - case DXGI_FORMAT_D24_UNORM_S8_UINT: - case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: - case DXGI_FORMAT_X24_TYPELESS_G8_UINT: - case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: - case DXGI_FORMAT_R8G8_B8G8_UNORM: - case DXGI_FORMAT_G8R8_G8B8_UNORM: - case DXGI_FORMAT_B8G8R8A8_UNORM: - case DXGI_FORMAT_B8G8R8X8_UNORM: - case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: - case DXGI_FORMAT_B8G8R8A8_TYPELESS: - case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: - case DXGI_FORMAT_B8G8R8X8_TYPELESS: - case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: - case DXGI_FORMAT_AYUV: - case DXGI_FORMAT_Y410: - case DXGI_FORMAT_YUY2: - return 32; - case DXGI_FORMAT_P010: - case DXGI_FORMAT_P016: - return 24; - case DXGI_FORMAT_R8G8_TYPELESS: - case DXGI_FORMAT_R8G8_UNORM: - case DXGI_FORMAT_R8G8_UINT: - case DXGI_FORMAT_R8G8_SNORM: - case DXGI_FORMAT_R8G8_SINT: - case DXGI_FORMAT_R16_TYPELESS: - case DXGI_FORMAT_R16_FLOAT: - case DXGI_FORMAT_D16_UNORM: - case DXGI_FORMAT_R16_UNORM: - case DXGI_FORMAT_R16_UINT: - case DXGI_FORMAT_R16_SNORM: - case DXGI_FORMAT_R16_SINT: - case DXGI_FORMAT_B5G6R5_UNORM: - case DXGI_FORMAT_B5G5R5A1_UNORM: - case DXGI_FORMAT_A8P8: - case DXGI_FORMAT_B4G4R4A4_UNORM: - return 16; - case DXGI_FORMAT_NV12: - case DXGI_FORMAT_420_OPAQUE: - case DXGI_FORMAT_NV11: - return 12; - case DXGI_FORMAT_R8_TYPELESS: - case DXGI_FORMAT_R8_UNORM: - case DXGI_FORMAT_R8_UINT: - case DXGI_FORMAT_R8_SNORM: - case DXGI_FORMAT_R8_SINT: - case DXGI_FORMAT_A8_UNORM: - case DXGI_FORMAT_AI44: - case DXGI_FORMAT_IA44: - case DXGI_FORMAT_P8: - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return 8; - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC4_SNORM: - return 4; - case DXGI_FORMAT_R1_UNORM: - return 1; - default: - return 0; - } -} - HRESULT WINAPI D3DX10GetImageInfoFromFileA(const char *src_file, ID3DX10ThreadPump *pump, D3DX10_IMAGE_INFO *info, HRESULT *result) { @@ -806,146 +630,16 @@ void init_load_info(const D3DX10_IMAGE_LOAD_INFO *load_info, D3DX10_IMAGE_LOAD_I out->pSrcInfo = NULL; }
-static HRESULT convert_image(IWICImagingFactory *factory, IWICBitmapFrameDecode *frame, - const GUID *dst_format, unsigned int stride, unsigned int frame_size, BYTE *buffer) -{ - IWICFormatConverter *converter; - BOOL can_convert; - GUID src_format; - HRESULT hr; - - if (FAILED(hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &src_format))) - return hr; - - if (IsEqualGUID(&src_format, dst_format)) - { - if (FAILED(hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, stride, frame_size, buffer))) - return hr; - return S_OK; - } - - if (FAILED(hr = IWICImagingFactory_CreateFormatConverter(factory, &converter))) - return hr; - if (FAILED(hr = IWICFormatConverter_CanConvert(converter, &src_format, dst_format, &can_convert))) - { - IWICFormatConverter_Release(converter); - return hr; - } - if (!can_convert) - { - WARN("Format converting %s to %s is not supported by WIC.\n", - debugstr_guid(&src_format), debugstr_guid(dst_format)); - IWICFormatConverter_Release(converter); - return E_NOTIMPL; - } - if (FAILED(hr = IWICFormatConverter_Initialize(converter, (IWICBitmapSource *)frame, dst_format, - WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom))) - { - IWICFormatConverter_Release(converter); - return hr; - } - hr = IWICFormatConverter_CopyPixels(converter, NULL, stride, frame_size, buffer); - IWICFormatConverter_Release(converter); - return hr; -} - -static HRESULT d3dx_load_texture_data(struct d3dx_image *image, D3DX10_IMAGE_LOAD_INFO *load_info, - const D3DX10_IMAGE_INFO *img_info, D3D10_SUBRESOURCE_DATA **resource_data) +HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO *load_info, + D3D10_SUBRESOURCE_DATA **resource_data) { const struct pixel_format_desc *fmt_desc, *src_desc; - D3DX10_IMAGE_LOAD_INFO tmp_load_info = *load_info; BYTE *res_data = NULL, *pixels_buffer; uint32_t pixels_size, pixels_offset; - unsigned int i, j; - HRESULT hr = S_OK; - - tmp_load_info.Format = img_info->Format; - fmt_desc = get_d3dx_pixel_format_info(d3dx_pixel_format_id_from_dxgi_format(tmp_load_info.Format)); - if (fmt_desc->format == D3DX_PIXEL_FORMAT_COUNT) - { - FIXME("Unknown DXGI format supplied, %#x.\n", tmp_load_info.Format); - return E_NOTIMPL; - } - - /* Potentially round up width/height to align with block size. */ - tmp_load_info.Width = (img_info->Width + fmt_desc->block_width - 1) & ~(fmt_desc->block_width - 1); - tmp_load_info.Height = (img_info->Height + fmt_desc->block_height - 1) & ~(fmt_desc->block_height - 1); - tmp_load_info.Depth = img_info->Depth; - tmp_load_info.MipLevels = img_info->MipLevels; - - pixels_size = d3dx_calculate_layer_pixels_size(fmt_desc->format, tmp_load_info.Width, tmp_load_info.Height, - tmp_load_info.Depth, tmp_load_info.MipLevels) * img_info->ArraySize; - pixels_offset = (sizeof(**resource_data) * tmp_load_info.MipLevels * img_info->ArraySize); - if (!(res_data = malloc(pixels_size + pixels_offset))) - return E_FAIL; - - pixels_buffer = res_data + pixels_offset; - *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data; - - src_desc = get_d3dx_pixel_format_info(image->format); - for (i = 0; i < img_info->ArraySize; ++i) - { - struct volume dst_size = { tmp_load_info.Width, tmp_load_info.Height, tmp_load_info.Depth }; - - for (j = 0; j < tmp_load_info.MipLevels; ++j) - { - const RECT unaligned_rect = { 0, 0, dst_size.width, dst_size.height }; - struct d3dx_pixels src_pixels, dst_pixels; - uint32_t dst_row_pitch, dst_slice_pitch; - - hr = d3dx_image_get_pixels(image, i, j, &src_pixels); - if (FAILED(hr)) - break; - - hr = d3dx_calculate_pixels_size(fmt_desc->format, dst_size.width, dst_size.height, &dst_row_pitch, - &dst_slice_pitch); - if (FAILED(hr)) - break; - - set_d3dx_pixels(&dst_pixels, pixels_buffer, dst_row_pitch, dst_slice_pitch, NULL, dst_size.width, - dst_size.height, dst_size.depth, &unaligned_rect); - - hr = d3dx_load_pixels_from_pixels(&dst_pixels, fmt_desc, &src_pixels, src_desc, D3DX10_FILTER_POINT, 0); - if (FAILED(hr)) - break; - - (*resource_data)[i * tmp_load_info.MipLevels + j].pSysMem = pixels_buffer; - (*resource_data)[i * tmp_load_info.MipLevels + j].SysMemPitch = dst_row_pitch; - (*resource_data)[i * tmp_load_info.MipLevels + j].SysMemSlicePitch = dst_slice_pitch; - - pixels_buffer += dst_slice_pitch * dst_size.depth; - d3dx_get_next_mip_level_size(&dst_size); - } - } - - if (FAILED(hr)) - { - *resource_data = NULL; - free(res_data); - return hr; - } - - *load_info = tmp_load_info; - load_info->Usage = D3D10_USAGE_DEFAULT; - load_info->BindFlags = D3D10_BIND_SHADER_RESOURCE; - load_info->MiscFlags = img_info->MiscFlags; - - return S_OK; -} - -HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO *load_info, - D3D10_SUBRESOURCE_DATA **resource_data) -{ - IWICBitmapFrameDecode *frame = NULL; - IWICImagingFactory *factory = NULL; - IWICBitmapDecoder *decoder = NULL; - unsigned int stride, frame_size; - BYTE *res_data = NULL, *buffer; D3DX10_IMAGE_INFO img_info; - IWICStream *stream = NULL; struct d3dx_image image; - const GUID *dst_format; - HRESULT hr; + unsigned int i, j; + HRESULT hr = S_OK;
if (!data || !size) return E_FAIL; @@ -977,6 +671,7 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO if (load_info->pSrcInfo) FIXME("load_info->pSrcInfo is ignored.\n");
+ *resource_data = NULL; hr = d3dx_image_init(data, size, &image, 0, D3DX_IMAGE_SUPPORT_DXT10); if (FAILED(hr)) return E_FAIL; @@ -997,74 +692,84 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO goto end; }
- if (SUCCEEDED(hr = d3dx_load_texture_data(&image, load_info, &img_info, resource_data))) + load_info->Format = img_info.Format; + fmt_desc = get_d3dx_pixel_format_info(d3dx_pixel_format_id_from_dxgi_format(load_info->Format)); + if (fmt_desc->format == D3DX_PIXEL_FORMAT_COUNT) { - TRACE("Successfully used shared code to load texture data.\n"); - res_data = NULL; + FIXME("Unknown DXGI format supplied, %#x.\n", load_info->Format); + hr = E_NOTIMPL; goto end; } - else if (img_info.ImageFileFormat == D3DX10_IFF_DDS) + + /* Potentially round up width/height to align with block size. */ + load_info->Width = (img_info.Width + fmt_desc->block_width - 1) & ~(fmt_desc->block_width - 1); + load_info->Height = (img_info.Height + fmt_desc->block_height - 1) & ~(fmt_desc->block_height - 1); + load_info->Depth = img_info.Depth; + load_info->MipLevels = img_info.MipLevels; + + pixels_size = d3dx_calculate_layer_pixels_size(fmt_desc->format, load_info->Width, load_info->Height, + load_info->Depth, load_info->MipLevels) * img_info.ArraySize; + pixels_offset = (sizeof(**resource_data) * load_info->MipLevels * img_info.ArraySize); + if (!(res_data = malloc(pixels_size + pixels_offset))) { + hr = E_OUTOFMEMORY; goto end; }
- if (FAILED(hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory))) - goto end; - if (FAILED(hr = IWICImagingFactory_CreateStream(factory, &stream))) - goto end; - if (FAILED(hr = IWICStream_InitializeFromMemory(stream, (BYTE *)data, size))) - goto end; - if (FAILED(hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream *)stream, NULL, 0, &decoder))) - goto end; - if (FAILED(hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame))) - goto end; - - stride = (img_info.Width * get_bpp_from_format(img_info.Format) + 7) / 8; - frame_size = stride * img_info.Height; + pixels_buffer = res_data + pixels_offset; + *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data;
- if (!(res_data = malloc(sizeof(**resource_data) + frame_size))) + src_desc = get_d3dx_pixel_format_info(image.format); + for (i = 0; i < img_info.ArraySize; ++i) { - hr = E_FAIL; - goto end; + struct volume dst_size = { load_info->Width, load_info->Height, load_info->Depth }; + + for (j = 0; j < load_info->MipLevels; ++j) + { + const RECT unaligned_rect = { 0, 0, dst_size.width, dst_size.height }; + struct d3dx_pixels src_pixels, dst_pixels; + uint32_t dst_row_pitch, dst_slice_pitch; + + hr = d3dx_image_get_pixels(&image, i, j, &src_pixels); + if (FAILED(hr)) + break; + + hr = d3dx_calculate_pixels_size(fmt_desc->format, dst_size.width, dst_size.height, &dst_row_pitch, + &dst_slice_pitch); + if (FAILED(hr)) + break; + + set_d3dx_pixels(&dst_pixels, pixels_buffer, dst_row_pitch, dst_slice_pitch, NULL, dst_size.width, + dst_size.height, dst_size.depth, &unaligned_rect); + + hr = d3dx_load_pixels_from_pixels(&dst_pixels, fmt_desc, &src_pixels, src_desc, D3DX10_FILTER_POINT, 0); + if (FAILED(hr)) + break; + + (*resource_data)[i * load_info->MipLevels + j].pSysMem = pixels_buffer; + (*resource_data)[i * load_info->MipLevels + j].SysMemPitch = dst_row_pitch; + (*resource_data)[i * load_info->MipLevels + j].SysMemSlicePitch = dst_slice_pitch; + + pixels_buffer += dst_slice_pitch * dst_size.depth; + d3dx_get_next_mip_level_size(&dst_size); + } } - buffer = res_data + sizeof(**resource_data);
- if (!(dst_format = dxgi_format_to_wic_guid(img_info.Format))) + if (FAILED(hr)) { - hr = E_FAIL; - FIXME("Unsupported DXGI format %#x.\n", img_info.Format); + *resource_data = NULL; goto end; } - if (FAILED(hr = convert_image(factory, frame, dst_format, stride, frame_size, buffer))) - goto end;
- *resource_data = (D3D10_SUBRESOURCE_DATA *)res_data; - (*resource_data)->pSysMem = buffer; - (*resource_data)->SysMemPitch = stride; - (*resource_data)->SysMemSlicePitch = frame_size; - - load_info->Width = img_info.Width; - load_info->Height = img_info.Height; - load_info->MipLevels = img_info.MipLevels; - load_info->Format = img_info.Format; load_info->Usage = D3D10_USAGE_DEFAULT; load_info->BindFlags = D3D10_BIND_SHADER_RESOURCE; load_info->MiscFlags = img_info.MiscFlags;
res_data = NULL; - hr = S_OK;
end: d3dx_image_cleanup(&image); free(res_data); - if (frame) - IWICBitmapFrameDecode_Release(frame); - if (decoder) - IWICBitmapDecoder_Release(decoder); - if (stream) - IWICStream_Release(stream); - if (factory) - IWICImagingFactory_Release(factory); return hr; }
On Mon Sep 29 21:59:33 2025 +0000, Matteo Bruni wrote:
I'd mention explicitly that we're doing it to be safe and until we find reason to do otherwise.
I've expanded the code comment here in the current revision, hopefully its more clear.
On Tue Sep 30 10:49:33 2025 +0000, Connor McAdams wrote:
I wrote this patch awhile ago, I _think_ I used the term optimization to bolster my argument for changing this behavior. It technically should be faster as it lets us get out of this function earlier. The decompressed values don't change with this "optimization". The actual compressed data values shouldn't really matter, what should matter is the decompressed values. But, in `check_texture{2d,3d}_data()`, we check for compressed values. What would be a better term to use here? Just "Wine specific change"?
So, in general I'd expect a change described as "optimization" to only affect performance, not output values. There are cases where there isn't this kind of expectation (e.g. compiler optimization settings will change generated code, although that in turn shouldn't usually behave differently) and, as things are, I don't think this one is much of an abuse of the term "optimization".
Still, I do slightly prefer "change", as you mentioned, or something similar (tweak?)
On Tue Sep 30 11:46:50 2025 +0000, Connor McAdams wrote:
I've yet to find any explicit mention of the default filter type for d3dx10/d3dx11 in the documentation, but I doubt that it's a point filter :) I intend on writing some tests to try and figure it out now that I have some understanding of the different filter types. Since we don't handle the `Filter` member in the passed in `D3DX10_IMAGE_LOAD_INFO` and the default type is unknown, I've just defaulted to point here. I can print a `FIXME()` somewhere around here if that'd help clarify, or maybe a code comment.
Got it. Adding a `FIXME()` if / when we figure out that the default filter is not _POINT might be a good idea, but this seems fine for now.