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,