From: Connor McAdams cmcadams@codeweavers.com
Windowscodecs has no WIC format for this, and cannot do conversion from it.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx10_43/tests/d3dx10.c | 23 ++++++ dlls/d3dx10_43/texture.c | 140 +++++++++++++++++++++++++++++++++- 2 files changed, 162 insertions(+), 1 deletion(-)
diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 5853669d9c5..f9bf3aae4d7 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -343,6 +343,25 @@ static const BYTE test_dds_16bpp_data[] = 0x84, 0x84, 0x73, 0xff };
+/* 1x1 16bpp dds image */ +static const BYTE test_dds_16bpp_bgra[] = +{ + 0x44, 0x44, 0x53, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, + 0xf0, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x12, 0x34, +}; + +static const BYTE test_dds_16bpp_bgra_data[] = +{ + 0x44, 0x11, 0x22, 0x33 +}; + /* 1x1 24bpp dds image */ static const BYTE test_dds_24bpp[] = { @@ -796,6 +815,10 @@ test_image[] = test_dds_16bpp, sizeof(test_dds_16bpp), test_dds_16bpp_data, {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3DX10_IFF_DDS} }, + { + test_dds_16bpp_bgra, sizeof(test_dds_16bpp_bgra), test_dds_16bpp_bgra_data, + {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3DX10_IFF_DDS} + }, { test_dds_24bpp, sizeof(test_dds_24bpp), test_dds_24bpp_data, {1, 1, 1, 1, 1, 0, DXGI_FORMAT_R8G8B8A8_UNORM, D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3DX10_IFF_DDS} diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c index b925a07dd08..6854627d6ab 100644 --- a/dlls/d3dx10_43/texture.c +++ b/dlls/d3dx10_43/texture.c @@ -276,6 +276,138 @@ static DXGI_FORMAT get_d3dx10_dds_format(DXGI_FORMAT format) return format; }
+/* DDS format helper functions. */ +#define DDS_MAGIC 0x20534444 +#define GET_MAGIC(buf_ptr) (*((DWORD *)buf_ptr)) + +#define GET_B4G4R4A4_R(ptr) ((((BYTE *)ptr)[1]) & 0x0f) +#define GET_B4G4R4A4_G(ptr) (((((BYTE *)ptr)[0]) & 0xf0) >> 4) +#define GET_B4G4R4A4_B(ptr) ((((BYTE *)ptr)[0]) & 0x0f) +#define GET_B4G4R4A4_A(ptr) (((((BYTE *)ptr)[1]) & 0xf0) >> 4) + +#define GET_R8G8B8A8_R(ptr) (((BYTE *)ptr)[0]) +#define GET_R8G8B8A8_G(ptr) (((BYTE *)ptr)[1]) +#define GET_R8G8B8A8_B(ptr) (((BYTE *)ptr)[2]) +#define GET_R8G8B8A8_A(ptr) (((BYTE *)ptr)[3]) + +#define DDPF_RGB 0x00000040 + +typedef struct { + DWORD size; + DWORD flags; + DWORD fourCC; + DWORD rgbBitCount; + DWORD rBitMask; + DWORD gBitMask; + DWORD bBitMask; + DWORD aBitMask; +} DDS_PIXELFORMAT; + +typedef struct { + DWORD size; + DWORD flags; + DWORD height; + DWORD width; + DWORD pitchOrLinearSize; + DWORD depth; + DWORD mipMapCount; + DWORD reserved1[11]; + DDS_PIXELFORMAT ddspf; + DWORD caps; + DWORD caps2; + DWORD caps3; + DWORD caps4; + DWORD reserved2; +} DDS_HEADER; + +#define DDS_HEADER_OFFSET sizeof(DWORD) +#define DDS_TEXTURE_DATA_OFFSET DDS_HEADER_OFFSET + sizeof(DDS_HEADER) +static const struct dds_format_conversion { + DDS_PIXELFORMAT src_pixel_format; + DDS_PIXELFORMAT dst_pixel_format; +} dds_format_conversion_table[] = { + { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 16, 0xF00,0xF0,0xF,0xF000 }, /* DXGI_FORMAT_B4G4R4A4_UNORM */ + { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 32, 0xFF,0xFF00,0xFF0000,0xFF000000 }, }, /* DXGI_FORMAT_R8G8B8A8_UNORM */ +}; + +static const struct dds_format_conversion *get_dds_format_conversion(const DDS_PIXELFORMAT *pixel_format) +{ + UINT i; + + for (i = 0; i < ARRAY_SIZE(dds_format_conversion_table); i++) + { + if ((pixel_format->flags & dds_format_conversion_table[i].src_pixel_format.flags) && + (pixel_format->fourCC == dds_format_conversion_table[i].src_pixel_format.fourCC) && + (pixel_format->rgbBitCount == dds_format_conversion_table[i].src_pixel_format.rgbBitCount) && + (pixel_format->rBitMask == dds_format_conversion_table[i].src_pixel_format.rBitMask) && + (pixel_format->gBitMask == dds_format_conversion_table[i].src_pixel_format.gBitMask) && + (pixel_format->bBitMask == dds_format_conversion_table[i].src_pixel_format.bBitMask) && + (pixel_format->aBitMask == dds_format_conversion_table[i].src_pixel_format.aBitMask)) + return dds_format_conversion_table + i; + } + + return NULL; +} + +static void dds_conversion_check(const void *data, SIZE_T size, const void **ret_data, SIZE_T *ret_size) +{ + unsigned int src_tex_bytes_per_pixel, dst_tex_bytes_per_pixel, src_tex_stride, dst_tex_stride, i, x; + const struct dds_format_conversion *dds_format_conversion; + SIZE_T src_tex_data_size, dst_tex_data_size; + const DDS_HEADER *dds_header; + const BYTE *src_data = data; + DDS_HEADER *dds_header_new; + BYTE *buf; + + *ret_data = data; + *ret_size = size; + if (!data || (size < DDS_HEADER_OFFSET) || (GET_MAGIC(data) != DDS_MAGIC)) + return; + + dds_header = (const DDS_HEADER *)(src_data + DDS_HEADER_OFFSET); + if (!(dds_format_conversion = get_dds_format_conversion(&dds_header->ddspf))) + return; + + TRACE("Doing DDS conversion.\n"); + + src_tex_data_size = size - ((src_data + DDS_TEXTURE_DATA_OFFSET) - src_data); + src_tex_bytes_per_pixel = dds_header->ddspf.rgbBitCount / 8; + src_tex_stride = dds_header->pitchOrLinearSize; + if (!src_tex_stride) + src_tex_stride = dds_header->width * src_tex_bytes_per_pixel; + + dst_tex_bytes_per_pixel = dds_format_conversion->dst_pixel_format.rgbBitCount / 8; + dst_tex_stride = (src_tex_stride / src_tex_bytes_per_pixel) * dst_tex_bytes_per_pixel; + dst_tex_data_size = (src_tex_data_size / src_tex_bytes_per_pixel) * dst_tex_bytes_per_pixel; + + buf = malloc(DDS_TEXTURE_DATA_OFFSET + dst_tex_data_size); + memcpy(buf, data, sizeof(DWORD)); /* Copy magic value. */ + + dds_header_new = (DDS_HEADER *)(buf + DDS_HEADER_OFFSET); + *dds_header_new = *dds_header; + dds_header_new->ddspf = dds_format_conversion->dst_pixel_format; + dds_header_new->pitchOrLinearSize = dst_tex_stride; + + for (i = 0; i < dds_header->height; i++) + { + const BYTE *src_tex_data = (src_data + DDS_TEXTURE_DATA_OFFSET) + (i * src_tex_stride); + BYTE *dst_tex_data = (buf + DDS_TEXTURE_DATA_OFFSET) + (i * dst_tex_stride); + + for (x = 0; x < dds_header->width; x++) + { + GET_R8G8B8A8_R(dst_tex_data) = GET_B4G4R4A4_R(src_tex_data) * 17; + GET_R8G8B8A8_G(dst_tex_data) = GET_B4G4R4A4_G(src_tex_data) * 17; + GET_R8G8B8A8_B(dst_tex_data) = GET_B4G4R4A4_B(src_tex_data) * 17; + GET_R8G8B8A8_A(dst_tex_data) = GET_B4G4R4A4_A(src_tex_data) * 17; + src_tex_data += src_tex_bytes_per_pixel; + dst_tex_data += dst_tex_bytes_per_pixel; + } + } + + *ret_data = buf; + *ret_size = dst_tex_data_size + DDS_TEXTURE_DATA_OFFSET; +} + HRESULT WINAPI D3DX10GetImageInfoFromFileA(const char *src_file, ID3DX10ThreadPump *pump, D3DX10_IMAGE_INFO *info, HRESULT *result) { @@ -819,7 +951,7 @@ static HRESULT convert_image(IWICImagingFactory *factory, IWICBitmapFrameDecode return hr; }
-HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO *load_info, +HRESULT load_texture_data(const void *src_data, SIZE_T src_size, D3DX10_IMAGE_LOAD_INFO *load_info, D3D10_SUBRESOURCE_DATA **resource_data) { unsigned int stride, frame_size, i, j; @@ -832,8 +964,12 @@ HRESULT load_texture_data(const void *data, SIZE_T size, D3DX10_IMAGE_LOAD_INFO D3DX10_IMAGE_INFO img_info; IWICStream *stream = NULL; const GUID *dst_format; + void *data = NULL; + SIZE_T size = 0; HRESULT hr;
+ dds_conversion_check(src_data, src_size, (const void **)&data, &size); + if (load_info->Width != D3DX10_DEFAULT) FIXME("load_info->Width is ignored.\n"); if (load_info->Height != D3DX10_DEFAULT) @@ -1021,6 +1157,8 @@ end: IWICStream_Release(stream); if (factory) IWICImagingFactory_Release(factory); + if (src_data != data) + free(data); return hr; }