This series of patches introduces a new set of structures and functions that will enable code to be re-used across various functions in d3dx9, and eventually d3dx10-d3dx11. It might be possible to split this further, but I feel like this initial set gives better context as to where things are heading.
I have a [branch](https://gitlab.winehq.org/cmcadams/wine/-/commits/WIP/d3dx-shared-source-v03...) that uses these structures and functions in d3dx10 if further context would be useful. There are a lot of changes here, but after playing around with different approaches this was the best/cleanest way I could come up with for code sharing. I'm sure there will be things I missed or potentially ways to improve this, I'm open to suggestions of course. :)
-- v2: d3dx9: Use d3dx_load_pixels_from_pixels() in D3DXLoadVolumeFromMemory(). d3dx9: Use d3dx_pixels structure in decompression helper function. d3dx9: Introduce d3dx_load_pixels_from_pixels() helper function. d3dx9: Use d3dx_image structure in D3DXLoadSurfaceFromFileInMemory(). d3dx9: Introduce d3dx_image structure for use in D3DXGetImageInfoFromFileInMemory(). d3dx9: Refactor WIC image info retrieval code in D3DXGetImageInfoFromFileInMemory(). d3dx9: Refactor WIC GUID to D3DXIMAGE_FILEFORMAT conversion code.
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/surface.c | 79 +++++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 18 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index ef6cd57c7da..bf9096e3ec5 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -923,6 +923,59 @@ static BOOL image_is_argb(IWICBitmapFrameDecode *frame, const D3DXIMAGE_INFO *in return FALSE; }
+struct d3dx_wic_file_format +{ + const GUID *wic_container_guid; + D3DXIMAGE_FILEFORMAT d3dx_file_format; +}; + +/* Sorted by GUID. */ +static const struct d3dx_wic_file_format file_formats[] = +{ + { &GUID_ContainerFormatBmp, D3DXIFF_BMP }, + { &GUID_WineContainerFormatTga, D3DXIFF_TGA }, + { &GUID_ContainerFormatJpeg, D3DXIFF_JPG }, + { &GUID_ContainerFormatPng, D3DXIFF_PNG }, +}; + +static int __cdecl d3dx_wic_file_format_guid_compare(const void *a, const void *b) +{ + const struct d3dx_wic_file_format *format = b; + const GUID *guid = a; + + return memcmp(guid, format->wic_container_guid, sizeof(*guid)); +} + +static D3DXIMAGE_FILEFORMAT wic_container_guid_to_d3dx_file_format(GUID *container_format) +{ + struct d3dx_wic_file_format *format; + + if ((format = bsearch(container_format, file_formats, ARRAY_SIZE(file_formats), sizeof(*format), + d3dx_wic_file_format_guid_compare))) + return format->d3dx_file_format; + return D3DXIFF_FORCE_DWORD; +} + +static const char *debug_d3dx_image_file_format(D3DXIMAGE_FILEFORMAT format) +{ + switch (format) + { +#define FMT_TO_STR(format) case format: return #format + FMT_TO_STR(D3DXIFF_BMP); + FMT_TO_STR(D3DXIFF_JPG); + FMT_TO_STR(D3DXIFF_TGA); + FMT_TO_STR(D3DXIFF_PNG); + FMT_TO_STR(D3DXIFF_DDS); + FMT_TO_STR(D3DXIFF_PPM); + FMT_TO_STR(D3DXIFF_DIB); + FMT_TO_STR(D3DXIFF_HDR); + FMT_TO_STR(D3DXIFF_PFM); +#undef FMT_TO_STR + default: + return "unrecognized"; + } +} + /************************************************************ * D3DXGetImageInfoFromFileInMemory * @@ -993,27 +1046,17 @@ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(const void *data, UINT datasize,
hr = IWICBitmapDecoder_GetContainerFormat(decoder, &container_format); if (SUCCEEDED(hr)) { - if (IsEqualGUID(&container_format, &GUID_ContainerFormatBmp)) { - if (dib) { - TRACE("File type is DIB\n"); - info->ImageFileFormat = D3DXIFF_DIB; - } else { - TRACE("File type is BMP\n"); - info->ImageFileFormat = D3DXIFF_BMP; - } - } else if (IsEqualGUID(&container_format, &GUID_ContainerFormatPng)) { - TRACE("File type is PNG\n"); - info->ImageFileFormat = D3DXIFF_PNG; - } else if(IsEqualGUID(&container_format, &GUID_ContainerFormatJpeg)) { - TRACE("File type is JPG\n"); - info->ImageFileFormat = D3DXIFF_JPG; - } else if(IsEqualGUID(&container_format, &GUID_WineContainerFormatTga)) { - TRACE("File type is TGA\n"); - info->ImageFileFormat = D3DXIFF_TGA; - } else { + D3DXIMAGE_FILEFORMAT file_format = wic_container_guid_to_d3dx_file_format(&container_format); + + if (dib && file_format == D3DXIFF_BMP) file_format = D3DXIFF_DIB; + if (file_format == D3DXIFF_FORCE_DWORD) { WARN("Unsupported image file format %s\n", debugstr_guid(&container_format)); hr = D3DXERR_INVALIDDATA; } + else { + info->ImageFileFormat = file_format; + TRACE("File type is %s.\n", debug_d3dx_image_file_format(file_format)); + } }
if (SUCCEEDED(hr))
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/surface.c | 189 +++++++++++++++++++++------------------- 1 file changed, 99 insertions(+), 90 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index bf9096e3ec5..a9088dac8e4 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -976,6 +976,103 @@ static const char *debug_d3dx_image_file_format(D3DXIMAGE_FILEFORMAT format) } }
+static HRESULT get_image_info_from_wic(const void *src_data, uint32_t src_data_size, D3DXIMAGE_INFO *info) +{ + IWICBitmapFrameDecode *bitmap_frame = NULL; + IWICBitmapDecoder *bitmap_decoder = NULL; + uint32_t src_image_size = src_data_size; + IWICImagingFactory *wic_factory = NULL; + const void *src_image = src_data; + WICPixelFormatGUID pixel_format; + IWICStream *wic_stream = NULL; + uint32_t frame_count = 0; + GUID container_format; + BOOL is_dib = FALSE; + HRESULT hr; + + hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &wic_factory); + if (FAILED(hr)) + return hr; + + is_dib = convert_dib_to_bmp(&src_image, &src_image_size); + hr = IWICImagingFactory_CreateStream(wic_factory, &wic_stream); + if (FAILED(hr)) + goto exit; + + hr = IWICStream_InitializeFromMemory(wic_stream, (BYTE *)src_image, src_image_size); + if (FAILED(hr)) + goto exit; + + hr = IWICImagingFactory_CreateDecoderFromStream(wic_factory, (IStream *)wic_stream, NULL, 0, &bitmap_decoder); + if (FAILED(hr)) + { + if ((src_image_size >= 2) && (!strncmp(src_image, "P3", 2) || !strncmp(src_image, "P6", 2))) + FIXME("File type PPM is not supported yet.\n"); + else if ((src_image_size >= 10) && !strncmp(src_image, "#?RADIANCE", 10)) + FIXME("File type HDR is not supported yet.\n"); + else if ((src_image_size >= 2) && (!strncmp(src_image, "PF", 2) || !strncmp(src_image, "Pf", 2))) + FIXME("File type PFM is not supported yet.\n"); + goto exit; + } + + hr = IWICBitmapDecoder_GetContainerFormat(bitmap_decoder, &container_format); + if (FAILED(hr)) + goto exit; + + info->ImageFileFormat = wic_container_guid_to_d3dx_file_format(&container_format); + if (is_dib && info->ImageFileFormat == D3DXIFF_BMP) + info->ImageFileFormat = D3DXIFF_DIB; + else if (info->ImageFileFormat == D3DXIFF_FORCE_DWORD) + { + WARN("Unsupported image file format %s.\n", debugstr_guid(&container_format)); + hr = D3DXERR_INVALIDDATA; + goto exit; + } + + TRACE("File type is %s.\n", debug_d3dx_image_file_format(info->ImageFileFormat)); + hr = IWICBitmapDecoder_GetFrameCount(bitmap_decoder, &frame_count); + if (FAILED(hr) || (SUCCEEDED(hr) && !frame_count)) + { + hr = D3DXERR_INVALIDDATA; + goto exit; + } + + hr = IWICBitmapDecoder_GetFrame(bitmap_decoder, 0, &bitmap_frame); + if (FAILED(hr)) + goto exit; + + hr = IWICBitmapFrameDecode_GetSize(bitmap_frame, &info->Width, &info->Height); + if (FAILED(hr)) + goto exit; + + hr = IWICBitmapFrameDecode_GetPixelFormat(bitmap_frame, &pixel_format); + if (FAILED(hr)) + goto exit; + + if ((info->Format = wic_guid_to_d3dformat(&pixel_format)) == D3DFMT_UNKNOWN) + { + WARN("Unsupported pixel format %s.\n", debugstr_guid(&pixel_format)); + hr = D3DXERR_INVALIDDATA; + goto exit; + } + + if (image_is_argb(bitmap_frame, info)) + info->Format = D3DFMT_A8R8G8B8; + + info->Depth = 1; + info->MipLevels = 1; + info->ResourceType = D3DRTYPE_TEXTURE; + +exit: + if (is_dib) free((void *)src_image); + if (wic_factory) IWICImagingFactory_Release(wic_factory); + if (wic_stream) IWICStream_Release(wic_stream); + if (bitmap_decoder) IWICBitmapDecoder_Release(bitmap_decoder); + if (bitmap_frame) IWICBitmapFrameDecode_Release(bitmap_frame); + + return hr; +} + /************************************************************ * D3DXGetImageInfoFromFileInMemory * @@ -999,11 +1096,7 @@ static const char *debug_d3dx_image_file_format(D3DXIMAGE_FILEFORMAT format) */ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(const void *data, UINT datasize, D3DXIMAGE_INFO *info) { - IWICImagingFactory *factory; - IWICBitmapDecoder *decoder = NULL; - IWICStream *stream; HRESULT hr; - BOOL dib;
TRACE("(%p, %d, %p)\n", data, datasize, info);
@@ -1016,92 +1109,8 @@ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(const void *data, UINT datasize, if ((datasize >= 4) && !strncmp(data, "DDS ", 4)) { TRACE("File type is DDS\n"); return get_image_info_from_dds(data, datasize, info); - } - - /* In case of DIB file, convert it to BMP */ - dib = convert_dib_to_bmp(&data, &datasize); - - hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory); - - if (SUCCEEDED(hr)) { - IWICImagingFactory_CreateStream(factory, &stream); - IWICStream_InitializeFromMemory(stream, (BYTE*)data, datasize); - hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream*)stream, NULL, 0, &decoder); - IWICStream_Release(stream); - IWICImagingFactory_Release(factory); - } - - if (FAILED(hr)) { - if ((datasize >= 2) && (!strncmp(data, "P3", 2) || !strncmp(data, "P6", 2))) - FIXME("File type PPM is not supported yet\n"); - else if ((datasize >= 10) && !strncmp(data, "#?RADIANCE", 10)) - FIXME("File type HDR is not supported yet\n"); - else if ((datasize >= 2) && (!strncmp(data, "PF", 2) || !strncmp(data, "Pf", 2))) - FIXME("File type PFM is not supported yet\n"); - } - - if (SUCCEEDED(hr)) { - GUID container_format; - UINT frame_count; - - hr = IWICBitmapDecoder_GetContainerFormat(decoder, &container_format); - if (SUCCEEDED(hr)) { - D3DXIMAGE_FILEFORMAT file_format = wic_container_guid_to_d3dx_file_format(&container_format); - - if (dib && file_format == D3DXIFF_BMP) file_format = D3DXIFF_DIB; - if (file_format == D3DXIFF_FORCE_DWORD) { - WARN("Unsupported image file format %s\n", debugstr_guid(&container_format)); - hr = D3DXERR_INVALIDDATA; - } - else { - info->ImageFileFormat = file_format; - TRACE("File type is %s.\n", debug_d3dx_image_file_format(file_format)); - } - } - - if (SUCCEEDED(hr)) - hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count); - if (SUCCEEDED(hr) && !frame_count) - hr = D3DXERR_INVALIDDATA; - - if (SUCCEEDED(hr)) { - IWICBitmapFrameDecode *frame = NULL; - - hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); - - if (SUCCEEDED(hr)) - hr = IWICBitmapFrameDecode_GetSize(frame, &info->Width, &info->Height); - - if (SUCCEEDED(hr)) { - WICPixelFormatGUID pixel_format; - - hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &pixel_format); - if (SUCCEEDED(hr)) { - info->Format = wic_guid_to_d3dformat(&pixel_format); - if (info->Format == D3DFMT_UNKNOWN) { - WARN("Unsupported pixel format %s\n", debugstr_guid(&pixel_format)); - hr = D3DXERR_INVALIDDATA; - } - } - } - - if (SUCCEEDED(hr) && image_is_argb(frame, info)) - info->Format = D3DFMT_A8R8G8B8; - - if (frame) - IWICBitmapFrameDecode_Release(frame); - - info->Depth = 1; - info->MipLevels = 1; - info->ResourceType = D3DRTYPE_TEXTURE; - } - } - - if (decoder) - IWICBitmapDecoder_Release(decoder); - - if (dib) - free((void*)data); + } else + hr = get_image_info_from_wic(data, datasize, info);
if (FAILED(hr)) { TRACE("Invalid or unsupported image file\n");
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 13 +++ dlls/d3dx9_36/surface.c | 193 +++++++++++++++++----------------- 2 files changed, 109 insertions(+), 97 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 668fbb27b28..e28661bf9dd 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -68,6 +68,19 @@ struct pixel_format_desc { void (*to_rgba)(const struct vec4 *src, struct vec4 *dst, const PALETTEENTRY *palette); };
+struct d3dx_image +{ + D3DRESOURCETYPE resource_type; + D3DFORMAT format; + + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t mip_levels; + + D3DXIMAGE_FILEFORMAT image_file_format; +}; + struct d3dx_include_from_file { ID3DXInclude ID3DXInclude_iface; diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index a9088dac8e4..b7d11f9449a 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -481,78 +481,6 @@ static UINT calculate_dds_file_size(D3DFORMAT format, UINT width, UINT height, U return file_size; }
-/************************************************************ -* get_image_info_from_dds -* -* Fills a D3DXIMAGE_INFO structure with information -* about a DDS file stored in the memory. -* -* PARAMS -* buffer [I] pointer to DDS data -* length [I] size of DDS data -* info [O] pointer to D3DXIMAGE_INFO structure -* -* RETURNS -* Success: D3D_OK -* Failure: D3DXERR_INVALIDDATA -* -*/ -static HRESULT get_image_info_from_dds(const void *buffer, UINT length, D3DXIMAGE_INFO *info) -{ - UINT faces = 1; - UINT expected_length; - const struct dds_header *header = buffer; - - if (length < sizeof(*header) || !info) - return D3DXERR_INVALIDDATA; - - if (header->pixel_format.size != sizeof(header->pixel_format)) - return D3DXERR_INVALIDDATA; - - info->Width = header->width; - info->Height = header->height; - info->Depth = 1; - info->MipLevels = header->miplevels ? header->miplevels : 1; - - info->Format = dds_pixel_format_to_d3dformat(&header->pixel_format); - if (info->Format == D3DFMT_UNKNOWN) - return D3DXERR_INVALIDDATA; - - TRACE("Pixel format is %#x\n", info->Format); - - if (header->caps2 & DDS_CAPS2_VOLUME) - { - info->Depth = header->depth; - info->ResourceType = D3DRTYPE_VOLUMETEXTURE; - } - else if (header->caps2 & DDS_CAPS2_CUBEMAP) - { - DWORD face; - faces = 0; - for (face = DDS_CAPS2_CUBEMAP_POSITIVEX; face <= DDS_CAPS2_CUBEMAP_NEGATIVEZ; face <<= 1) - { - if (header->caps2 & face) - faces++; - } - info->ResourceType = D3DRTYPE_CUBETEXTURE; - } - else - { - info->ResourceType = D3DRTYPE_TEXTURE; - } - - expected_length = calculate_dds_file_size(info->Format, info->Width, info->Height, info->Depth, - info->MipLevels, faces); - if (length < expected_length) - { - WARN("File is too short %u, expected at least %u bytes\n", length, expected_length); - return D3DXERR_INVALIDDATA; - } - - info->ImageFileFormat = D3DXIFF_DDS; - return D3D_OK; -} - static HRESULT load_surface_from_dds(IDirect3DSurface9 *dst_surface, const PALETTEENTRY *dst_palette, const RECT *dst_rect, const void *src_data, const RECT *src_rect, DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info) @@ -822,6 +750,59 @@ HRESULT load_volume_texture_from_dds(IDirect3DVolumeTexture9 *volume_texture, co return D3D_OK; }
+static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src_data_size, + struct d3dx_image *image) +{ + const struct dds_header *header = src_data; + uint32_t expected_src_data_size; + uint32_t faces = 1; + + if (src_data_size < sizeof(*header) || header->pixel_format.size != sizeof(header->pixel_format)) + return D3DXERR_INVALIDDATA; + + TRACE("File type is DDS.\n"); + image->width = header->width; + image->height = header->height; + image->depth = 1; + image->mip_levels = header->miplevels ? header->miplevels : 1; + image->format = dds_pixel_format_to_d3dformat(&header->pixel_format); + + if (image->format == D3DFMT_UNKNOWN) + return D3DXERR_INVALIDDATA; + + TRACE("Pixel format is %#x.\n", image->format); + if (header->caps2 & DDS_CAPS2_VOLUME) + { + image->depth = header->depth; + image->resource_type = D3DRTYPE_VOLUMETEXTURE; + } + else if (header->caps2 & DDS_CAPS2_CUBEMAP) + { + DWORD face; + + faces = 0; + for (face = DDS_CAPS2_CUBEMAP_POSITIVEX; face <= DDS_CAPS2_CUBEMAP_NEGATIVEZ; face <<= 1) + { + if (header->caps2 & face) + faces++; + } + image->resource_type = D3DRTYPE_CUBETEXTURE; + } + else + image->resource_type = D3DRTYPE_TEXTURE; + + expected_src_data_size = calculate_dds_file_size(image->format, image->width, image->height, + image->depth, image->mip_levels, faces); + if (src_data_size < expected_src_data_size) + { + WARN("File is too short %u, expected at least %u bytes.\n", src_data_size, expected_src_data_size); + return D3DXERR_INVALIDDATA; + } + + image->image_file_format = D3DXIFF_DDS; + return D3D_OK; +} + static BOOL convert_dib_to_bmp(const void **data, unsigned int *size) { ULONG header_size; @@ -889,28 +870,28 @@ static BOOL convert_dib_to_bmp(const void **data, unsigned int *size)
/* windowscodecs always returns xRGB, but we should return ARGB if and only if * at least one pixel has a non-zero alpha component. */ -static BOOL image_is_argb(IWICBitmapFrameDecode *frame, const D3DXIMAGE_INFO *info) +static BOOL image_is_argb(IWICBitmapFrameDecode *frame, struct d3dx_image *image) { unsigned int size, i; BYTE *buffer; HRESULT hr;
- if (info->Format != D3DFMT_X8R8G8B8 || (info->ImageFileFormat != D3DXIFF_BMP - && info->ImageFileFormat != D3DXIFF_TGA)) + if (image->format != D3DFMT_X8R8G8B8 || (image->image_file_format != D3DXIFF_BMP + && image->image_file_format != D3DXIFF_TGA)) return FALSE;
- size = info->Width * info->Height * 4; + size = image->width * image->height * 4; if (!(buffer = malloc(size))) return FALSE;
- if (FAILED(hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, info->Width * 4, size, buffer))) + if (FAILED(hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, image->width * 4, size, buffer))) { ERR("Failed to copy pixels, hr %#lx.\n", hr); free(buffer); return FALSE; }
- for (i = 0; i < info->Width * info->Height; ++i) + for (i = 0; i < image->width * image->height; ++i) { if (buffer[i * 4 + 3]) { @@ -976,7 +957,8 @@ static const char *debug_d3dx_image_file_format(D3DXIMAGE_FILEFORMAT format) } }
-static HRESULT get_image_info_from_wic(const void *src_data, uint32_t src_data_size, D3DXIMAGE_INFO *info) +static HRESULT d3dx_initialize_image_from_wic(const void *src_data, uint32_t src_data_size, + struct d3dx_image *image) { IWICBitmapFrameDecode *bitmap_frame = NULL; IWICBitmapDecoder *bitmap_decoder = NULL; @@ -1019,17 +1001,17 @@ static HRESULT get_image_info_from_wic(const void *src_data, uint32_t src_data_s if (FAILED(hr)) goto exit;
- info->ImageFileFormat = wic_container_guid_to_d3dx_file_format(&container_format); - if (is_dib && info->ImageFileFormat == D3DXIFF_BMP) - info->ImageFileFormat = D3DXIFF_DIB; - else if (info->ImageFileFormat == D3DXIFF_FORCE_DWORD) + image->image_file_format = wic_container_guid_to_d3dx_file_format(&container_format); + if (is_dib && image->image_file_format == D3DXIFF_BMP) + image->image_file_format = D3DXIFF_DIB; + else if (image->image_file_format == D3DXIFF_FORCE_DWORD) { WARN("Unsupported image file format %s.\n", debugstr_guid(&container_format)); hr = D3DXERR_INVALIDDATA; goto exit; }
- TRACE("File type is %s.\n", debug_d3dx_image_file_format(info->ImageFileFormat)); + TRACE("File type is %s.\n", debug_d3dx_image_file_format(image->image_file_format)); hr = IWICBitmapDecoder_GetFrameCount(bitmap_decoder, &frame_count); if (FAILED(hr) || (SUCCEEDED(hr) && !frame_count)) { @@ -1041,7 +1023,7 @@ static HRESULT get_image_info_from_wic(const void *src_data, uint32_t src_data_s if (FAILED(hr)) goto exit;
- hr = IWICBitmapFrameDecode_GetSize(bitmap_frame, &info->Width, &info->Height); + hr = IWICBitmapFrameDecode_GetSize(bitmap_frame, &image->width, &image->height); if (FAILED(hr)) goto exit;
@@ -1049,19 +1031,19 @@ static HRESULT get_image_info_from_wic(const void *src_data, uint32_t src_data_s if (FAILED(hr)) goto exit;
- if ((info->Format = wic_guid_to_d3dformat(&pixel_format)) == D3DFMT_UNKNOWN) + if ((image->format = wic_guid_to_d3dformat(&pixel_format)) == D3DFMT_UNKNOWN) { WARN("Unsupported pixel format %s.\n", debugstr_guid(&pixel_format)); hr = D3DXERR_INVALIDDATA; goto exit; }
- if (image_is_argb(bitmap_frame, info)) - info->Format = D3DFMT_A8R8G8B8; + if (image_is_argb(bitmap_frame, image)) + image->format = D3DFMT_A8R8G8B8;
- info->Depth = 1; - info->MipLevels = 1; - info->ResourceType = D3DRTYPE_TEXTURE; + image->depth = 1; + image->mip_levels = 1; + image->resource_type = D3DRTYPE_TEXTURE;
exit: if (is_dib) free((void *)src_image); @@ -1073,6 +1055,19 @@ exit: return hr; }
+static HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, + struct d3dx_image *image) +{ + if (!src_data || !src_data_size || !image) + return D3DERR_INVALIDCALL; + + memset(image, 0, sizeof(*image)); + if ((src_data_size >= 4) && !strncmp(src_data, "DDS ", 4)) + return d3dx_initialize_image_from_dds(src_data, src_data_size, image); + + return d3dx_initialize_image_from_wic(src_data, src_data_size, image); +} + /************************************************************ * D3DXGetImageInfoFromFileInMemory * @@ -1096,6 +1091,7 @@ exit: */ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(const void *data, UINT datasize, D3DXIMAGE_INFO *info) { + struct d3dx_image image; HRESULT hr;
TRACE("(%p, %d, %p)\n", data, datasize, info); @@ -1106,17 +1102,20 @@ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(const void *data, UINT datasize, if (!info) return D3D_OK;
- if ((datasize >= 4) && !strncmp(data, "DDS ", 4)) { - TRACE("File type is DDS\n"); - return get_image_info_from_dds(data, datasize, info); - } else - hr = get_image_info_from_wic(data, datasize, info); - + hr = d3dx_image_init(data, datasize, &image); if (FAILED(hr)) { TRACE("Invalid or unsupported image file\n"); return D3DXERR_INVALIDDATA; }
+ info->ImageFileFormat = image.image_file_format; + info->Width = image.width; + info->Height = image.height; + info->Depth = image.depth; + info->MipLevels = image.mip_levels; + info->Format = image.format; + info->ResourceType = image.resource_type; + return D3D_OK; }
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 23 +++ dlls/d3dx9_36/surface.c | 319 +++++++++++++++------------------- 2 files changed, 164 insertions(+), 178 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index e28661bf9dd..0597d197060 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -68,6 +68,19 @@ struct pixel_format_desc { void (*to_rgba)(const struct vec4 *src, struct vec4 *dst, const PALETTEENTRY *palette); };
+struct d3dx_pixels +{ + const void *data; + uint32_t row_pitch; + uint32_t slice_pitch; + const PALETTEENTRY *palette; + + uint32_t width; + uint32_t height; + uint32_t depth; +}; + +#define D3DX_IMAGE_INFO_ONLY 1 struct d3dx_image { D3DRESOURCETYPE resource_type; @@ -78,6 +91,16 @@ struct d3dx_image uint32_t depth; uint32_t mip_levels;
+ BYTE *pixels; + + /* + * image_buf and palette are pointers to allocated memory used to store + * image data. If they are non-NULL, they need to be freed when no longer + * in use. + */ + void *image_buf; + PALETTEENTRY *palette; + D3DXIMAGE_FILEFORMAT image_file_format; };
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index b7d11f9449a..9d217ae1401 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -481,25 +481,6 @@ static UINT calculate_dds_file_size(D3DFORMAT format, UINT width, UINT height, U return file_size; }
-static HRESULT load_surface_from_dds(IDirect3DSurface9 *dst_surface, const PALETTEENTRY *dst_palette, - const RECT *dst_rect, const void *src_data, const RECT *src_rect, DWORD filter, D3DCOLOR color_key, - const D3DXIMAGE_INFO *src_info) -{ - UINT size; - UINT src_pitch; - const struct dds_header *header = src_data; - const BYTE *pixels = (BYTE *)(header + 1); - - if (src_info->ResourceType != D3DRTYPE_TEXTURE) - return D3DXERR_INVALIDDATA; - - if (FAILED(calculate_dds_surface_size(src_info->Format, src_info->Width, src_info->Height, &src_pitch, &size))) - return E_NOTIMPL; - - return D3DXLoadSurfaceFromMemory(dst_surface, dst_palette, dst_rect, pixels, src_info->Format, - src_pitch, NULL, src_rect, filter, color_key); -} - static HRESULT save_dds_surface_to_memory(ID3DXBuffer **dst_buffer, IDirect3DSurface9 *src_surface, const RECT *src_rect) { HRESULT hr; @@ -799,6 +780,7 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src return D3DXERR_INVALIDDATA; }
+ image->pixels = ((BYTE *)src_data) + sizeof(*header); image->image_file_format = D3DXIFF_DDS; return D3D_OK; } @@ -957,8 +939,81 @@ static const char *debug_d3dx_image_file_format(D3DXIMAGE_FILEFORMAT format) } }
+static HRESULT d3dx_image_wic_frame_decode(struct d3dx_image *image, + IWICImagingFactory *wic_factory, IWICBitmapFrameDecode *bitmap_frame) +{ + const struct pixel_format_desc *fmt_desc; + uint32_t row_pitch, slice_pitch; + IWICPalette *wic_palette = NULL; + PALETTEENTRY *palette = NULL; + WICColor *colors = NULL; + BYTE *buffer = NULL; + HRESULT hr; + + fmt_desc = get_format_info(image->format); + hr = calculate_dds_surface_size(image->format, image->width, image->height, &row_pitch, &slice_pitch); + if (FAILED(hr)) + return hr; + + /* Allocate a buffer for our image. */ + if (!(buffer = malloc(slice_pitch))) + return E_OUTOFMEMORY; + + hr = IWICBitmapFrameDecode_CopyPixels(bitmap_frame, NULL, row_pitch, slice_pitch, buffer); + if (FAILED(hr)) + { + free(buffer); + return hr; + } + + if (fmt_desc->type == FORMAT_INDEX) + { + uint32_t nb_colors, i; + + hr = IWICImagingFactory_CreatePalette(wic_factory, &wic_palette); + if (FAILED(hr)) goto exit; + + hr = IWICBitmapFrameDecode_CopyPalette(bitmap_frame, wic_palette); + if (FAILED(hr)) goto exit; + + hr = IWICPalette_GetColorCount(wic_palette, &nb_colors); + if (FAILED(hr)) goto exit; + + colors = malloc(nb_colors * sizeof(colors[0])); + palette = malloc(nb_colors * sizeof(palette[0])); + if (!colors || !palette) + { + hr = E_OUTOFMEMORY; + goto exit; + } + + hr = IWICPalette_GetColors(wic_palette, nb_colors, colors, &nb_colors); + if (FAILED(hr)) goto exit; + + /* Convert colors from WICColor (ARGB) to PALETTEENTRY (ABGR) */ + for (i = 0; i < nb_colors; i++) + { + palette[i].peRed = (colors[i] >> 16) & 0xff; + palette[i].peGreen = (colors[i] >> 8) & 0xff; + palette[i].peBlue = colors[i] & 0xff; + palette[i].peFlags = (colors[i] >> 24) & 0xff; /* peFlags is the alpha component in DX8 and higher */ + } + } + + image->image_buf = image->pixels = buffer; + image->palette = palette; + +exit: + free(colors); + if (image->image_buf != buffer) free(buffer); + if (image->palette != palette) free(palette); + if (wic_palette) IWICPalette_Release(wic_palette); + + return hr; +} + static HRESULT d3dx_initialize_image_from_wic(const void *src_data, uint32_t src_data_size, - struct d3dx_image *image) + struct d3dx_image *image, uint32_t flags) { IWICBitmapFrameDecode *bitmap_frame = NULL; IWICBitmapDecoder *bitmap_decoder = NULL; @@ -1041,6 +1096,13 @@ static HRESULT d3dx_initialize_image_from_wic(const void *src_data, uint32_t src if (image_is_argb(bitmap_frame, image)) image->format = D3DFMT_A8R8G8B8;
+ if (!(flags & D3DX_IMAGE_INFO_ONLY)) + { + hr = d3dx_image_wic_frame_decode(image, wic_factory, bitmap_frame); + if (FAILED(hr)) + goto exit; + } + image->depth = 1; image->mip_levels = 1; image->resource_type = D3DRTYPE_TEXTURE; @@ -1056,7 +1118,7 @@ exit: }
static HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, - struct d3dx_image *image) + struct d3dx_image *image, uint32_t flags) { if (!src_data || !src_data_size || !image) return D3DERR_INVALIDCALL; @@ -1065,7 +1127,44 @@ static HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, if ((src_data_size >= 4) && !strncmp(src_data, "DDS ", 4)) return d3dx_initialize_image_from_dds(src_data, src_data_size, image);
- return d3dx_initialize_image_from_wic(src_data, src_data_size, image); + return d3dx_initialize_image_from_wic(src_data, src_data_size, image, flags); +} + +static void d3dx_image_cleanup(struct d3dx_image *image) +{ + free(image->image_buf); + free(image->palette); +} + +static HRESULT d3dx_image_get_pixels(struct d3dx_image *image, struct d3dx_pixels *pixels) +{ + uint32_t row_pitch, slice_pitch; + HRESULT hr = S_OK; + + hr = calculate_dds_surface_size(image->format, image->width, image->height, &row_pitch, &slice_pitch); + if (FAILED(hr)) + return hr; + + pixels->data = image->pixels; + pixels->row_pitch = row_pitch; + pixels->slice_pitch = slice_pitch; + pixels->palette = image->palette; + pixels->width = image->width; + pixels->height = image->height; + pixels->depth = image->depth; + + return D3D_OK; +} + +static void d3dximage_info_from_d3dx_image(D3DXIMAGE_INFO *info, struct d3dx_image *image) +{ + info->ImageFileFormat = image->image_file_format; + info->Width = image->width; + info->Height = image->height; + info->Depth = image->depth; + info->MipLevels = image->mip_levels; + info->Format = image->format; + info->ResourceType = image->resource_type; }
/************************************************************ @@ -1102,20 +1201,13 @@ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(const void *data, UINT datasize, if (!info) return D3D_OK;
- hr = d3dx_image_init(data, datasize, &image); + hr = d3dx_image_init(data, datasize, &image, D3DX_IMAGE_INFO_ONLY); if (FAILED(hr)) { TRACE("Invalid or unsupported image file\n"); return D3DXERR_INVALIDDATA; }
- info->ImageFileFormat = image.image_file_format; - info->Width = image.width; - info->Height = image.height; - info->Depth = image.depth; - info->MipLevels = image.mip_levels; - info->Format = image.format; - info->ResourceType = image.resource_type; - + d3dximage_info_from_d3dx_image(info, &image); return D3D_OK; }
@@ -1244,18 +1336,12 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface, const PALETTEENTRY *pDestPalette, const RECT *pDestRect, const void *pSrcData, UINT SrcDataSize, const RECT *pSrcRect, DWORD dwFilter, D3DCOLOR Colorkey, D3DXIMAGE_INFO *pSrcInfo) { - D3DXIMAGE_INFO imginfo; + struct d3dx_pixels pixels = { 0 }; + struct d3dx_image image; + D3DXIMAGE_INFO img_info; + RECT src_rect; HRESULT hr;
- IWICImagingFactory *factory = NULL; - IWICBitmapDecoder *decoder; - IWICBitmapFrameDecode *bitmapframe; - IWICStream *stream; - - const struct pixel_format_desc *formatdesc; - WICRect wicrect; - RECT rect; - TRACE("dst_surface %p, dst_palette %p, dst_rect %s, src_data %p, src_data_size %u, " "src_rect %s, filter %#lx, color_key 0x%08lx, src_info %p.\n", pDestSurface, pDestPalette, wine_dbgstr_rect(pDestRect), pSrcData, SrcDataSize, @@ -1264,151 +1350,28 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface, if (!pDestSurface || !pSrcData || !SrcDataSize) return D3DERR_INVALIDCALL;
- hr = D3DXGetImageInfoFromFileInMemory(pSrcData, SrcDataSize, &imginfo); - + hr = d3dx_image_init(pSrcData, SrcDataSize, &image, 0); if (FAILED(hr)) - return hr; + return D3DXERR_INVALIDDATA;
+ d3dximage_info_from_d3dx_image(&img_info, &image); if (pSrcRect) - { - wicrect.X = pSrcRect->left; - wicrect.Y = pSrcRect->top; - wicrect.Width = pSrcRect->right - pSrcRect->left; - wicrect.Height = pSrcRect->bottom - pSrcRect->top; - } + src_rect = *pSrcRect; else - { - wicrect.X = 0; - wicrect.Y = 0; - wicrect.Width = imginfo.Width; - wicrect.Height = imginfo.Height; - } - - SetRect(&rect, wicrect.X, wicrect.Y, wicrect.X + wicrect.Width, wicrect.Y + wicrect.Height); - - if (imginfo.ImageFileFormat == D3DXIFF_DDS) - { - hr = load_surface_from_dds(pDestSurface, pDestPalette, pDestRect, pSrcData, &rect, - dwFilter, Colorkey, &imginfo); - if (SUCCEEDED(hr) && pSrcInfo) - *pSrcInfo = imginfo; - return hr; - } - - if (imginfo.ImageFileFormat == D3DXIFF_DIB) - convert_dib_to_bmp(&pSrcData, &SrcDataSize); - - if (FAILED(WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory))) - goto cleanup_err; - - if (FAILED(IWICImagingFactory_CreateStream(factory, &stream))) - { - IWICImagingFactory_Release(factory); - factory = NULL; - goto cleanup_err; - } - - IWICStream_InitializeFromMemory(stream, (BYTE*)pSrcData, SrcDataSize); - - hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream*)stream, NULL, 0, &decoder); - - IWICStream_Release(stream); + SetRect(&src_rect, 0, 0, img_info.Width, img_info.Height);
+ hr = d3dx_image_get_pixels(&image, &pixels); if (FAILED(hr)) - goto cleanup_err; - - hr = IWICBitmapDecoder_GetFrame(decoder, 0, &bitmapframe); - - if (FAILED(hr)) - goto cleanup_bmp; - - formatdesc = get_format_info(imginfo.Format); - - if (formatdesc->type == FORMAT_UNKNOWN) - { - FIXME("Unsupported pixel format\n"); - hr = D3DXERR_INVALIDDATA; - } - else - { - BYTE *buffer; - DWORD pitch; - PALETTEENTRY *palette = NULL; - WICColor *colors = NULL; - - pitch = formatdesc->bytes_per_pixel * wicrect.Width; - buffer = malloc(pitch * wicrect.Height); - - hr = IWICBitmapFrameDecode_CopyPixels(bitmapframe, &wicrect, pitch, - pitch * wicrect.Height, buffer); - - if (SUCCEEDED(hr) && (formatdesc->type == FORMAT_INDEX)) - { - IWICPalette *wic_palette = NULL; - UINT nb_colors; - - hr = IWICImagingFactory_CreatePalette(factory, &wic_palette); - if (SUCCEEDED(hr)) - hr = IWICBitmapFrameDecode_CopyPalette(bitmapframe, wic_palette); - if (SUCCEEDED(hr)) - hr = IWICPalette_GetColorCount(wic_palette, &nb_colors); - if (SUCCEEDED(hr)) - { - colors = malloc(nb_colors * sizeof(colors[0])); - palette = malloc(nb_colors * sizeof(palette[0])); - if (!colors || !palette) - hr = E_OUTOFMEMORY; - } - if (SUCCEEDED(hr)) - hr = IWICPalette_GetColors(wic_palette, nb_colors, colors, &nb_colors); - if (SUCCEEDED(hr)) - { - UINT i; - - /* Convert colors from WICColor (ARGB) to PALETTEENTRY (ABGR) */ - for (i = 0; i < nb_colors; i++) - { - palette[i].peRed = (colors[i] >> 16) & 0xff; - palette[i].peGreen = (colors[i] >> 8) & 0xff; - palette[i].peBlue = colors[i] & 0xff; - palette[i].peFlags = (colors[i] >> 24) & 0xff; /* peFlags is the alpha component in DX8 and higher */ - } - } - if (wic_palette) - IWICPalette_Release(wic_palette); - } - - if (SUCCEEDED(hr)) - { - hr = D3DXLoadSurfaceFromMemory(pDestSurface, pDestPalette, pDestRect, - buffer, imginfo.Format, pitch, - palette, &rect, dwFilter, Colorkey); - } - - free(colors); - free(palette); - free(buffer); - } - - IWICBitmapFrameDecode_Release(bitmapframe); - -cleanup_bmp: - IWICBitmapDecoder_Release(decoder); - -cleanup_err: - if (factory) - IWICImagingFactory_Release(factory); - - if (imginfo.ImageFileFormat == D3DXIFF_DIB) - free((void*)pSrcData); - - if (FAILED(hr)) - return D3DXERR_INVALIDDATA; + goto exit;
- if (pSrcInfo) - *pSrcInfo = imginfo; + hr = D3DXLoadSurfaceFromMemory(pDestSurface, pDestPalette, pDestRect, pixels.data, img_info.Format, + pixels.row_pitch, pixels.palette, &src_rect, dwFilter, Colorkey); + if (SUCCEEDED(hr) && pSrcInfo) + *pSrcInfo = img_info;
- return D3D_OK; +exit: + d3dx_image_cleanup(&image); + return FAILED(hr) ? D3DXERR_INVALIDDATA : D3D_OK; }
HRESULT WINAPI D3DXLoadSurfaceFromFileA(IDirect3DSurface9 *dst_surface,
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 1 + dlls/d3dx9_36/surface.c | 172 ++++++++++++++++++++++++---------- 2 files changed, 123 insertions(+), 50 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 0597d197060..b2fd2ccaaa3 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -78,6 +78,7 @@ struct d3dx_pixels uint32_t width; uint32_t height; uint32_t depth; + RECT unaligned_rect; };
#define D3DX_IMAGE_INFO_ONLY 1 diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 9d217ae1401..5c992106324 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1152,6 +1152,7 @@ static HRESULT d3dx_image_get_pixels(struct d3dx_image *image, struct d3dx_pixel pixels->width = image->width; pixels->height = image->height; pixels->depth = image->depth; + SetRect(&pixels->unaligned_rect, 0, 0, pixels->width, pixels->height);
return D3D_OK; } @@ -1952,6 +1953,45 @@ exit: return S_OK; }
+static HRESULT d3dx_pixels_init(const void *data, uint32_t row_pitch, uint32_t slice_pitch, + const PALETTEENTRY *palette, D3DFORMAT format, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, + uint32_t front, uint32_t back, struct d3dx_pixels *pixels) +{ + const struct pixel_format_desc *fmt_desc = get_format_info(format); + const BYTE *ptr = data; + + memset(pixels, 0, sizeof(*pixels)); + if (fmt_desc->type == FORMAT_UNKNOWN) + { + FIXME("Unsupported format %#x.\n", format); + return E_NOTIMPL; + } + + ptr += front * slice_pitch; + ptr += (top / fmt_desc->block_height) * row_pitch; + ptr += (left / fmt_desc->block_width) * fmt_desc->block_byte_count; + + pixels->data = ptr; + pixels->row_pitch = row_pitch; + pixels->slice_pitch = slice_pitch; + pixels->palette = palette; + pixels->width = right - left; + pixels->height = bottom - top; + pixels->depth = back - front; + + if (fmt_desc->type == FORMAT_DXT) + { + int32_t left_aligned, top_aligned; + + top_aligned = top & ~(fmt_desc->block_height - 1); + left_aligned = left & ~(fmt_desc->block_width - 1); + SetRect(&pixels->unaligned_rect, left, top, right, bottom); + OffsetRect(&pixels->unaligned_rect, -left_aligned, -top_aligned); + } + + return S_OK; +} + static void set_volume_struct(struct volume *volume, uint32_t width, uint32_t height, uint32_t depth) { volume->width = width; @@ -1959,40 +1999,52 @@ static void set_volume_struct(struct volume *volume, uint32_t width, uint32_t he volume->depth = depth; }
-static HRESULT d3dx_load_image_from_memory(void *dst_memory, uint32_t dst_row_pitch, const struct pixel_format_desc *dst_desc, - const PALETTEENTRY *dst_palette, const RECT *dst_rect, const RECT *dst_rect_aligned, const void *src_memory, - uint32_t src_row_pitch, const struct pixel_format_desc *src_desc, const PALETTEENTRY *src_palette, const RECT *src_rect, - uint32_t filter_flags, uint32_t color_key) +static const char *debug_d3dx_pixels(struct d3dx_pixels *pixels) +{ + if (!pixels) + return "(null)"; + return wine_dbg_sprintf("(data %p, row_pitch %d, slice_pitch %d, palette %p, width %d, height %d, depth %d, " + "unaligned_rect %s)", pixels->data, pixels->row_pitch, pixels->slice_pitch, pixels->palette, + pixels->width, pixels->height, pixels->depth, wine_dbgstr_rect(&pixels->unaligned_rect)); +} + +static HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, + const struct pixel_format_desc *dst_desc, struct d3dx_pixels *src_pixels, + const struct pixel_format_desc *src_desc, uint32_t filter_flags, uint32_t color_key) { struct volume src_size, dst_size, dst_size_aligned; - const BYTE *src_memory_offset = src_memory; HRESULT hr = S_OK;
- TRACE("dst_memory %p, dst_row_pitch %d, dst_desc %p, dst_palette %p, dst_rect %s, dst_rect_aligned %s, src_memory %p, " - "src_row_pitch %d, src_desc %p, src_palette %p, src_rect %s, filter %#x, color_key 0x%08x.\n", - dst_memory, dst_row_pitch, dst_desc, dst_palette, wine_dbgstr_rect(dst_rect), wine_dbgstr_rect(dst_rect_aligned), - src_memory, src_row_pitch, src_desc, src_palette, wine_dbgstr_rect(src_rect), filter_flags, color_key); + TRACE("dst_pixels %s, dst_desc %p, src_pixels %s, src_desc %p, filter_flags %#x, color_key %#x.\n", + debug_d3dx_pixels(dst_pixels), dst_desc, debug_d3dx_pixels(src_pixels), src_desc, + filter_flags, color_key);
- set_volume_struct(&src_size, (src_rect->right - src_rect->left), (src_rect->bottom - src_rect->top), 1); - set_volume_struct(&dst_size, (dst_rect->right - dst_rect->left), (dst_rect->bottom - dst_rect->top), 1); - set_volume_struct(&dst_size_aligned, (dst_rect_aligned->right - dst_rect_aligned->left), - (dst_rect_aligned->bottom - dst_rect_aligned->top), 1); + if (src_desc->type == FORMAT_DXT) + set_volume_struct(&src_size, (src_pixels->unaligned_rect.right - src_pixels->unaligned_rect.left), + (src_pixels->unaligned_rect.bottom - src_pixels->unaligned_rect.top), src_pixels->depth); + else + set_volume_struct(&src_size, src_pixels->width, src_pixels->height, src_pixels->depth);
- src_memory_offset += (src_rect->top / src_desc->block_height) * src_row_pitch; - src_memory_offset += (src_rect->left / src_desc->block_width) * src_desc->block_byte_count; + set_volume_struct(&dst_size_aligned, dst_pixels->width, dst_pixels->height, dst_pixels->depth); + if (dst_desc->type == FORMAT_DXT) + set_volume_struct(&dst_size, (dst_pixels->unaligned_rect.right - dst_pixels->unaligned_rect.left), + (dst_pixels->unaligned_rect.bottom - dst_pixels->unaligned_rect.top), dst_pixels->depth); + else + dst_size = dst_size_aligned;
/* Everything matches, simply copy the pixels. */ if (src_desc->format == dst_desc->format && (dst_size.width == src_size.width && !(dst_size.width % dst_desc->block_width)) && (dst_size.height == src_size.height && !(dst_size.height % dst_desc->block_height)) && color_key == 0 - && !(src_rect->left & (src_desc->block_width - 1)) - && !(src_rect->top & (src_desc->block_height - 1)) - && !(dst_rect->left & (dst_desc->block_width - 1)) - && !(dst_rect->top & (dst_desc->block_height - 1))) + && !(src_pixels->unaligned_rect.left & (src_desc->block_width - 1)) + && !(src_pixels->unaligned_rect.top & (src_desc->block_height - 1)) + && !(dst_pixels->unaligned_rect.left & (dst_desc->block_width - 1)) + && !(dst_pixels->unaligned_rect.top & (dst_desc->block_height - 1))) { TRACE("Simple copy.\n"); - copy_pixels(src_memory_offset, src_row_pitch, 0, dst_memory, dst_row_pitch, 0, &src_size, src_desc); + copy_pixels(src_pixels->data, src_pixels->row_pitch, src_pixels->slice_pitch, (void *)dst_pixels->data, + dst_pixels->row_pitch, dst_pixels->slice_pitch, &src_size, src_desc); return S_OK; }
@@ -2015,37 +2067,43 @@ static HRESULT d3dx_load_image_from_memory(void *dst_memory, uint32_t dst_row_pi void *uncompressed_mem = NULL; RECT uncompressed_rect;
- hr = d3dx_image_decompress(src_memory, src_row_pitch, src_rect, NULL, &src_size, src_desc, - &uncompressed_mem, &uncompressed_row_pitch, &uncompressed_rect, &uncompressed_desc); + hr = d3dx_image_decompress(src_pixels->data, src_pixels->row_pitch, &src_pixels->unaligned_rect, NULL, + &src_size, src_desc, &uncompressed_mem, &uncompressed_row_pitch, &uncompressed_rect, &uncompressed_desc); if (SUCCEEDED(hr)) { - hr = d3dx_load_image_from_memory(dst_memory, dst_row_pitch, dst_desc, dst_palette, dst_rect, dst_rect_aligned, - uncompressed_mem, uncompressed_row_pitch, uncompressed_desc, src_palette, &uncompressed_rect, + struct d3dx_pixels uncompressed_pixels; + + d3dx_pixels_init((const void *)uncompressed_mem, uncompressed_row_pitch, 0, NULL, uncompressed_desc->format, + 0, 0, src_pixels->width, src_pixels->height, 0, src_pixels->depth, &uncompressed_pixels); + + hr = d3dx_load_pixels_from_pixels(dst_pixels, dst_desc, &uncompressed_pixels, uncompressed_desc, filter_flags, color_key); } free(uncompressed_mem); - return hr; + goto exit; }
/* Same as the above, need to decompress the destination prior to modifying. */ if (dst_desc->type == FORMAT_DXT) { const struct pixel_format_desc *uncompressed_desc; + struct d3dx_pixels uncompressed_pixels; + RECT uncompressed_rect, aligned_rect; uint32_t uncompressed_row_pitch; void *uncompressed_mem = NULL; - BYTE *uncompressed_mem_offset; - RECT uncompressed_rect;
- hr = d3dx_image_decompress(dst_memory, dst_row_pitch, dst_rect_aligned, dst_rect, &dst_size_aligned, dst_desc, - &uncompressed_mem, &uncompressed_row_pitch, &uncompressed_rect, &uncompressed_desc); + SetRect(&aligned_rect, 0, 0, dst_pixels->width, dst_pixels->height); + hr = d3dx_image_decompress(dst_pixels->data, dst_pixels->row_pitch, &aligned_rect, + &dst_pixels->unaligned_rect, &dst_size_aligned, dst_desc, &uncompressed_mem, &uncompressed_row_pitch, + &uncompressed_rect, &uncompressed_desc); if (FAILED(hr)) - return hr; + goto exit;
- uncompressed_mem_offset = (BYTE *)uncompressed_mem + (dst_rect->top - dst_rect_aligned->top) * uncompressed_row_pitch - + (dst_rect->left - dst_rect_aligned->left) * uncompressed_desc->bytes_per_pixel; - hr = d3dx_load_image_from_memory(uncompressed_mem_offset, uncompressed_row_pitch, uncompressed_desc, dst_palette, - &uncompressed_rect, &uncompressed_rect, src_memory, src_row_pitch, src_desc, src_palette, - src_rect, filter_flags, color_key); + d3dx_pixels_init((const void *)uncompressed_mem, uncompressed_row_pitch, 0, NULL, + uncompressed_desc->format, dst_pixels->unaligned_rect.left, dst_pixels->unaligned_rect.top, + dst_pixels->unaligned_rect.right, dst_pixels->unaligned_rect.bottom, 0, 1, &uncompressed_pixels); + hr = d3dx_load_pixels_from_pixels(&uncompressed_pixels, uncompressed_desc, src_pixels, src_desc, filter_flags, + color_key); if (SUCCEEDED(hr)) { GLenum gl_format = 0; @@ -2068,16 +2126,17 @@ static HRESULT d3dx_load_image_from_memory(void *dst_memory, uint32_t dst_row_pi ERR("Unexpected destination compressed format %u.\n", dst_desc->format); } tx_compress_dxtn(4, dst_size_aligned.width, dst_size_aligned.height, uncompressed_mem, gl_format, - dst_memory, dst_row_pitch); + (BYTE *)dst_pixels->data, dst_pixels->row_pitch); } free(uncompressed_mem); - return hr; + goto exit; }
if ((filter_flags & 0xf) == D3DX_FILTER_NONE) { - convert_argb_pixels(src_memory_offset, src_row_pitch, 0, &src_size, src_desc, - dst_memory, dst_row_pitch, 0, &dst_size, dst_desc, color_key, src_palette); + convert_argb_pixels(src_pixels->data, src_pixels->row_pitch, src_pixels->slice_pitch, &src_size, src_desc, + (BYTE *)dst_pixels->data, dst_pixels->row_pitch, dst_pixels->slice_pitch, &dst_size, dst_desc, + color_key, src_pixels->palette); } else /* if ((filter & 0xf) == D3DX_FILTER_POINT) */ { @@ -2086,10 +2145,14 @@ static HRESULT d3dx_load_image_from_memory(void *dst_memory, uint32_t dst_row_pi
/* Always apply a point filter until D3DX_FILTER_LINEAR, * D3DX_FILTER_TRIANGLE and D3DX_FILTER_BOX are implemented. */ - point_filter_argb_pixels(src_memory_offset, src_row_pitch, 0, &src_size, src_desc, dst_memory, dst_row_pitch, 0, - &dst_size, dst_desc, color_key, src_palette); + point_filter_argb_pixels(src_pixels->data, src_pixels->row_pitch, src_pixels->slice_pitch, &src_size, + src_desc, (BYTE *)dst_pixels->data, dst_pixels->row_pitch, dst_pixels->slice_pitch, &dst_size, + dst_desc, color_key, src_pixels->palette); }
+exit: + if (FAILED(hr)) + WARN("Failed to load pixels, hr %#lx.\n", hr); return hr; }
@@ -2130,8 +2193,9 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, D3DFORMAT src_format, UINT src_pitch, const PALETTEENTRY *src_palette, const RECT *src_rect, DWORD filter, D3DCOLOR color_key) { - RECT dst_rect_temp, dst_rect_aligned, dst_locked_rect, dst_locked_rect_aligned; const struct pixel_format_desc *srcformatdesc, *destformatdesc; + struct d3dx_pixels src_pixels, dst_pixels; + RECT dst_rect_temp, dst_rect_aligned; IDirect3DSurface9 *surface; D3DSURFACE_DESC surfdesc; D3DLOCKED_RECT lockrect; @@ -2203,17 +2267,25 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, if (filter == D3DX_DEFAULT) filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
+ hr = d3dx_pixels_init(src_memory, src_pitch, 0, src_palette, srcformatdesc->format, + src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1, &src_pixels); + if (FAILED(hr)) + return hr; + if (FAILED(hr = lock_surface(dst_surface, &dst_rect_aligned, &lockrect, &surface, TRUE))) return hr;
- dst_locked_rect_aligned = dst_rect_aligned; - dst_locked_rect = *dst_rect; - OffsetRect(&dst_locked_rect_aligned, -dst_rect_aligned.left, -dst_rect_aligned.top); - OffsetRect(&dst_locked_rect, -dst_rect_aligned.left, -dst_rect_aligned.top); - hr = d3dx_load_image_from_memory(lockrect.pBits, lockrect.Pitch, destformatdesc, dst_palette, &dst_locked_rect, - &dst_locked_rect_aligned, src_memory, src_pitch, srcformatdesc, src_palette, src_rect, filter, color_key); - if (FAILED(hr)) - WARN("d3dx_load_image_from_memory failed with hr %#lx\n", hr); + dst_pixels.data = lockrect.pBits; + dst_pixels.row_pitch = lockrect.Pitch; + dst_pixels.slice_pitch = 0; + dst_pixels.palette = dst_palette; + dst_pixels.width = dst_rect_aligned.right - dst_rect_aligned.left; + dst_pixels.height = dst_rect_aligned.bottom - dst_rect_aligned.top; + dst_pixels.depth = 1; + dst_pixels.unaligned_rect = *dst_rect; + OffsetRect(&dst_pixels.unaligned_rect, -dst_rect_aligned.left, -dst_rect_aligned.top); + + d3dx_load_pixels_from_pixels(&dst_pixels, destformatdesc, &src_pixels, srcformatdesc, filter, color_key);
return unlock_surface(dst_surface, &dst_rect_aligned, surface, TRUE); }
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/surface.c | 61 +++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 26 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 5c992106324..ea7986f6bb1 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1890,9 +1890,8 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic } }
-static HRESULT d3dx_image_decompress(const void *memory, uint32_t row_pitch, const RECT *rect, - const RECT *unaligned_rect, const struct volume *size, const struct pixel_format_desc *desc, - void **out_memory, uint32_t *out_row_pitch, RECT *out_rect, const struct pixel_format_desc **out_desc) +static HRESULT d3dx_pixels_decompress(struct d3dx_pixels *pixels, const struct pixel_format_desc *desc, + BOOL is_dst, void **out_memory, uint32_t *out_row_pitch, const struct pixel_format_desc **out_desc) { void (*fetch_dxt_texel)(int srcRowStride, const BYTE *pixdata, int i, int j, void *texel); const struct pixel_format_desc *uncompressed_desc = NULL; @@ -1920,34 +1919,48 @@ static HRESULT d3dx_image_decompress(const void *memory, uint32_t row_pitch, con return E_NOTIMPL; }
- if (!(uncompressed_mem = malloc(size->width * size->height * size->depth * uncompressed_desc->bytes_per_pixel))) + if (!(uncompressed_mem = malloc(pixels->width * pixels->height * pixels->depth * uncompressed_desc->bytes_per_pixel))) return E_OUTOFMEMORY;
- if (unaligned_rect && EqualRect(rect, unaligned_rect)) - goto exit; + /* + * For compressed destination pixels, width/height will represent + * the entire set of compressed blocks our destination rectangle touches. + * If we're only updating a sub-area of any blocks, we need to decompress + * the pixels outside of the sub-area. + */ + if (is_dst) + { + const RECT aligned_rect = { 0, 0, pixels->width, pixels->height };
- TRACE("Decompressing image.\n"); - tmp_pitch = row_pitch * desc->block_width / desc->block_byte_count; - for (y = 0; y < size->height; ++y) + /* + * If our destination covers the entire set of blocks, no + * decompression needs to be done, just return the allocated memory. + */ + if (EqualRect(&aligned_rect, &pixels->unaligned_rect)) + goto exit; + } + + TRACE("Decompressing pixels.\n"); + tmp_pitch = pixels->row_pitch * desc->block_width / desc->block_byte_count; + for (y = 0; y < pixels->height; ++y) { - BYTE *ptr = &uncompressed_mem[y * size->width * uncompressed_desc->bytes_per_pixel]; - for (x = 0; x < size->width; ++x) + BYTE *ptr = &uncompressed_mem[y * pixels->width * uncompressed_desc->bytes_per_pixel]; + for (x = 0; x < pixels->width; ++x) { const POINT pt = { x, y };
- if (!PtInRect(unaligned_rect, pt)) - fetch_dxt_texel(tmp_pitch, (BYTE *)memory, x + rect->left, y + rect->top, ptr); + if (!is_dst) + fetch_dxt_texel(tmp_pitch, (BYTE *)pixels->data, x + pixels->unaligned_rect.left, + y + pixels->unaligned_rect.top, ptr); + else if (!PtInRect(&pixels->unaligned_rect, pt)) + fetch_dxt_texel(tmp_pitch, (BYTE *)pixels->data, x, y, ptr); ptr += uncompressed_desc->bytes_per_pixel; } }
exit: *out_memory = uncompressed_mem; - *out_row_pitch = size->width * uncompressed_desc->bytes_per_pixel; - if (unaligned_rect) - *out_rect = *unaligned_rect; - else - SetRect(out_rect, 0, 0, size->width, size->height); + *out_row_pitch = pixels->width * uncompressed_desc->bytes_per_pixel; *out_desc = uncompressed_desc;
return S_OK; @@ -2065,10 +2078,9 @@ static HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, const struct pixel_format_desc *uncompressed_desc; uint32_t uncompressed_row_pitch; void *uncompressed_mem = NULL; - RECT uncompressed_rect;
- hr = d3dx_image_decompress(src_pixels->data, src_pixels->row_pitch, &src_pixels->unaligned_rect, NULL, - &src_size, src_desc, &uncompressed_mem, &uncompressed_row_pitch, &uncompressed_rect, &uncompressed_desc); + hr = d3dx_pixels_decompress(src_pixels, src_desc, FALSE, &uncompressed_mem, &uncompressed_row_pitch, + &uncompressed_desc); if (SUCCEEDED(hr)) { struct d3dx_pixels uncompressed_pixels; @@ -2088,14 +2100,11 @@ static HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, { const struct pixel_format_desc *uncompressed_desc; struct d3dx_pixels uncompressed_pixels; - RECT uncompressed_rect, aligned_rect; uint32_t uncompressed_row_pitch; void *uncompressed_mem = NULL;
- SetRect(&aligned_rect, 0, 0, dst_pixels->width, dst_pixels->height); - hr = d3dx_image_decompress(dst_pixels->data, dst_pixels->row_pitch, &aligned_rect, - &dst_pixels->unaligned_rect, &dst_size_aligned, dst_desc, &uncompressed_mem, &uncompressed_row_pitch, - &uncompressed_rect, &uncompressed_desc); + hr = d3dx_pixels_decompress(dst_pixels, dst_desc, TRUE, &uncompressed_mem, &uncompressed_row_pitch, + &uncompressed_desc); if (FAILED(hr)) goto exit;
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 8 ++ dlls/d3dx9_36/surface.c | 106 ++++++++++++++---------- dlls/d3dx9_36/tests/volume.c | 2 +- dlls/d3dx9_36/volume.c | 146 ++++++++++++---------------------- 4 files changed, 127 insertions(+), 135 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index b2fd2ccaaa3..9d59ebda3d2 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -165,6 +165,14 @@ HRESULT lock_surface(IDirect3DSurface9 *surface, const RECT *surface_rect, D3DLO IDirect3DSurface9 **temp_surface, BOOL write); HRESULT unlock_surface(IDirect3DSurface9 *surface, const RECT *surface_rect, IDirect3DSurface9 *temp_surface, BOOL update); +HRESULT d3dx_pixels_init(const void *data, uint32_t row_pitch, uint32_t slice_pitch, + const PALETTEENTRY *palette, D3DFORMAT format, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, + uint32_t front, uint32_t back, struct d3dx_pixels *pixels); +HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, + const struct pixel_format_desc *dst_desc, struct d3dx_pixels *src_pixels, + const struct pixel_format_desc *src_desc, uint32_t filter_flags, uint32_t color_key); +void get_aligned_rect(uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, uint32_t width, uint32_t height, + const struct pixel_format_desc *fmt_desc, RECT *aligned_rect);
unsigned short float_32_to_16(const float in); float float_16_to_32(const unsigned short in); diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index ea7986f6bb1..f6d6e759b0e 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1891,11 +1891,12 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic }
static HRESULT d3dx_pixels_decompress(struct d3dx_pixels *pixels, const struct pixel_format_desc *desc, - BOOL is_dst, void **out_memory, uint32_t *out_row_pitch, const struct pixel_format_desc **out_desc) + BOOL is_dst, void **out_memory, uint32_t *out_row_pitch, uint32_t *out_slice_pitch, + const struct pixel_format_desc **out_desc) { void (*fetch_dxt_texel)(int srcRowStride, const BYTE *pixdata, int i, int j, void *texel); + uint32_t x, y, z, tmp_pitch, uncompressed_slice_pitch, uncompressed_row_pitch; const struct pixel_format_desc *uncompressed_desc = NULL; - uint32_t x, y, tmp_pitch; BYTE *uncompressed_mem;
switch (desc->format) @@ -1919,7 +1920,9 @@ static HRESULT d3dx_pixels_decompress(struct d3dx_pixels *pixels, const struct p return E_NOTIMPL; }
- if (!(uncompressed_mem = malloc(pixels->width * pixels->height * pixels->depth * uncompressed_desc->bytes_per_pixel))) + uncompressed_row_pitch = pixels->width * uncompressed_desc->bytes_per_pixel; + uncompressed_slice_pitch = uncompressed_row_pitch * pixels->height; + if (!(uncompressed_mem = malloc(pixels->depth * uncompressed_slice_pitch))) return E_OUTOFMEMORY;
/* @@ -1942,31 +1945,37 @@ static HRESULT d3dx_pixels_decompress(struct d3dx_pixels *pixels, const struct p
TRACE("Decompressing pixels.\n"); tmp_pitch = pixels->row_pitch * desc->block_width / desc->block_byte_count; - for (y = 0; y < pixels->height; ++y) + for (z = 0; z < pixels->depth; ++z) { - BYTE *ptr = &uncompressed_mem[y * pixels->width * uncompressed_desc->bytes_per_pixel]; - for (x = 0; x < pixels->width; ++x) + const BYTE *slice_data = ((BYTE *)pixels->data) + (pixels->slice_pitch * z); + + for (y = 0; y < pixels->height; ++y) { - const POINT pt = { x, y }; - - if (!is_dst) - fetch_dxt_texel(tmp_pitch, (BYTE *)pixels->data, x + pixels->unaligned_rect.left, - y + pixels->unaligned_rect.top, ptr); - else if (!PtInRect(&pixels->unaligned_rect, pt)) - fetch_dxt_texel(tmp_pitch, (BYTE *)pixels->data, x, y, ptr); - ptr += uncompressed_desc->bytes_per_pixel; + BYTE *ptr = &uncompressed_mem[(z * uncompressed_slice_pitch) + (y * uncompressed_row_pitch)]; + for (x = 0; x < pixels->width; ++x) + { + const POINT pt = { x, y }; + + if (!is_dst) + fetch_dxt_texel(tmp_pitch, slice_data, x + pixels->unaligned_rect.left, + y + pixels->unaligned_rect.top, ptr); + else if (!PtInRect(&pixels->unaligned_rect, pt)) + fetch_dxt_texel(tmp_pitch, slice_data, x, y, ptr); + ptr += uncompressed_desc->bytes_per_pixel; + } } }
exit: *out_memory = uncompressed_mem; - *out_row_pitch = pixels->width * uncompressed_desc->bytes_per_pixel; + *out_row_pitch = uncompressed_row_pitch; + *out_slice_pitch = uncompressed_slice_pitch; *out_desc = uncompressed_desc;
return S_OK; }
-static HRESULT d3dx_pixels_init(const void *data, uint32_t row_pitch, uint32_t slice_pitch, +HRESULT d3dx_pixels_init(const void *data, uint32_t row_pitch, uint32_t slice_pitch, const PALETTEENTRY *palette, D3DFORMAT format, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, uint32_t front, uint32_t back, struct d3dx_pixels *pixels) { @@ -2021,7 +2030,7 @@ static const char *debug_d3dx_pixels(struct d3dx_pixels *pixels) pixels->width, pixels->height, pixels->depth, wine_dbgstr_rect(&pixels->unaligned_rect)); }
-static HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, +HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, const struct pixel_format_desc *dst_desc, struct d3dx_pixels *src_pixels, const struct pixel_format_desc *src_desc, uint32_t filter_flags, uint32_t color_key) { @@ -2049,6 +2058,7 @@ static HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, if (src_desc->format == dst_desc->format && (dst_size.width == src_size.width && !(dst_size.width % dst_desc->block_width)) && (dst_size.height == src_size.height && !(dst_size.height % dst_desc->block_height)) + && (dst_size.depth == src_size.depth) && color_key == 0 && !(src_pixels->unaligned_rect.left & (src_desc->block_width - 1)) && !(src_pixels->unaligned_rect.top & (src_desc->block_height - 1)) @@ -2075,18 +2085,19 @@ static HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, */ if (src_desc->type == FORMAT_DXT) { + uint32_t uncompressed_row_pitch, uncompressed_slice_pitch; const struct pixel_format_desc *uncompressed_desc; - uint32_t uncompressed_row_pitch; void *uncompressed_mem = NULL;
hr = d3dx_pixels_decompress(src_pixels, src_desc, FALSE, &uncompressed_mem, &uncompressed_row_pitch, - &uncompressed_desc); + &uncompressed_slice_pitch, &uncompressed_desc); if (SUCCEEDED(hr)) { struct d3dx_pixels uncompressed_pixels;
- d3dx_pixels_init((const void *)uncompressed_mem, uncompressed_row_pitch, 0, NULL, uncompressed_desc->format, - 0, 0, src_pixels->width, src_pixels->height, 0, src_pixels->depth, &uncompressed_pixels); + d3dx_pixels_init((const void *)uncompressed_mem, uncompressed_row_pitch, + uncompressed_slice_pitch, NULL, uncompressed_desc->format, 0, 0, src_pixels->width, + src_pixels->height, 0, src_pixels->depth, &uncompressed_pixels);
hr = d3dx_load_pixels_from_pixels(dst_pixels, dst_desc, &uncompressed_pixels, uncompressed_desc, filter_flags, color_key); @@ -2098,24 +2109,26 @@ static HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, /* Same as the above, need to decompress the destination prior to modifying. */ if (dst_desc->type == FORMAT_DXT) { + uint32_t uncompressed_row_pitch, uncompressed_slice_pitch; const struct pixel_format_desc *uncompressed_desc; struct d3dx_pixels uncompressed_pixels; - uint32_t uncompressed_row_pitch; void *uncompressed_mem = NULL;
hr = d3dx_pixels_decompress(dst_pixels, dst_desc, TRUE, &uncompressed_mem, &uncompressed_row_pitch, - &uncompressed_desc); + &uncompressed_slice_pitch, &uncompressed_desc); if (FAILED(hr)) goto exit;
- d3dx_pixels_init((const void *)uncompressed_mem, uncompressed_row_pitch, 0, NULL, - uncompressed_desc->format, dst_pixels->unaligned_rect.left, dst_pixels->unaligned_rect.top, - dst_pixels->unaligned_rect.right, dst_pixels->unaligned_rect.bottom, 0, 1, &uncompressed_pixels); + d3dx_pixels_init((const void *)uncompressed_mem, uncompressed_row_pitch, + uncompressed_slice_pitch, NULL, uncompressed_desc->format, dst_pixels->unaligned_rect.left, + dst_pixels->unaligned_rect.top, dst_pixels->unaligned_rect.right, + dst_pixels->unaligned_rect.bottom, 0, dst_pixels->depth, &uncompressed_pixels); hr = d3dx_load_pixels_from_pixels(&uncompressed_pixels, uncompressed_desc, src_pixels, src_desc, filter_flags, color_key); if (SUCCEEDED(hr)) { GLenum gl_format = 0; + uint32_t i;
TRACE("Compressing DXTn surface.\n"); switch (dst_desc->format) @@ -2134,8 +2147,15 @@ static HRESULT d3dx_load_pixels_from_pixels(struct d3dx_pixels *dst_pixels, default: ERR("Unexpected destination compressed format %u.\n", dst_desc->format); } - tx_compress_dxtn(4, dst_size_aligned.width, dst_size_aligned.height, uncompressed_mem, gl_format, - (BYTE *)dst_pixels->data, dst_pixels->row_pitch); + + for (i = 0; i < dst_size_aligned.depth; ++i) + { + BYTE *uncompressed_mem_slice = (BYTE *)uncompressed_mem + (i * uncompressed_slice_pitch); + BYTE *dst_memory_slice = ((BYTE *)dst_pixels->data) + (i * dst_pixels->slice_pitch); + + tx_compress_dxtn(4, dst_size_aligned.width, dst_size_aligned.height, uncompressed_mem_slice, gl_format, + dst_memory_slice, dst_pixels->row_pitch); + } } free(uncompressed_mem); goto exit; @@ -2165,6 +2185,22 @@ exit: return hr; }
+void get_aligned_rect(uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, uint32_t width, uint32_t height, + const struct pixel_format_desc *fmt_desc, RECT *aligned_rect) +{ + SetRect(aligned_rect, left, top, right, bottom); + if (aligned_rect->left & (fmt_desc->block_width - 1)) + aligned_rect->left = aligned_rect->left & ~(fmt_desc->block_width - 1); + if (aligned_rect->top & (fmt_desc->block_height - 1)) + aligned_rect->top = aligned_rect->top & ~(fmt_desc->block_height - 1); + if (aligned_rect->right & (fmt_desc->block_width - 1) && aligned_rect->right != width) + aligned_rect->right = min((aligned_rect->right + fmt_desc->block_width - 1) + & ~(fmt_desc->block_width - 1), width); + if (aligned_rect->bottom & (fmt_desc->block_height - 1) && aligned_rect->bottom != height) + aligned_rect->bottom = min((aligned_rect->bottom + fmt_desc->block_height - 1) + & ~(fmt_desc->block_height - 1), height); +} + /************************************************************ * D3DXLoadSurfaceFromMemory * @@ -2261,18 +2297,6 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, } }
- dst_rect_aligned = *dst_rect; - if (dst_rect_aligned.left & (destformatdesc->block_width - 1)) - dst_rect_aligned.left = dst_rect_aligned.left & ~(destformatdesc->block_width - 1); - if (dst_rect_aligned.top & (destformatdesc->block_height - 1)) - dst_rect_aligned.top = dst_rect_aligned.top & ~(destformatdesc->block_height - 1); - if (dst_rect_aligned.right & (destformatdesc->block_width - 1) && dst_rect_aligned.right != surfdesc.Width) - dst_rect_aligned.right = min((dst_rect_aligned.right + destformatdesc->block_width - 1) - & ~(destformatdesc->block_width - 1), surfdesc.Width); - if (dst_rect_aligned.bottom & (destformatdesc->block_height - 1) && dst_rect_aligned.bottom != surfdesc.Height) - dst_rect_aligned.bottom = min((dst_rect_aligned.bottom + destformatdesc->block_height - 1) - & ~(destformatdesc->block_height - 1), surfdesc.Height); - if (filter == D3DX_DEFAULT) filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
@@ -2281,6 +2305,8 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, if (FAILED(hr)) return hr;
+ get_aligned_rect(dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, surfdesc.Width, surfdesc.Height, + destformatdesc, &dst_rect_aligned); if (FAILED(hr = lock_surface(dst_surface, &dst_rect_aligned, &lockrect, &surface, TRUE))) return hr;
diff --git a/dlls/d3dx9_36/tests/volume.c b/dlls/d3dx9_36/tests/volume.c index 52075aa6314..f990221f06b 100644 --- a/dlls/d3dx9_36/tests/volume.c +++ b/dlls/d3dx9_36/tests/volume.c @@ -205,7 +205,7 @@ static void test_D3DXLoadVolumeFromMemory(IDirect3DDevice9 *device) set_box(&src_box, 1, 1, 7, 7, 0, 1); set_box(&dst_box, 1, 1, 7, 7, 0, 1); hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, 32, NULL, &src_box, D3DX_DEFAULT, 0); - todo_wine ok(hr == D3D_OK, "D3DXLoadVolumeFromMemory returned %#lx, expected %#lx\n", hr, D3D_OK); + ok(hr == D3D_OK, "D3DXLoadVolumeFromMemory returned %#lx, expected %#lx\n", hr, D3D_OK);
IDirect3DVolume9_Release(volume); IDirect3DVolumeTexture9_Release(volume_texture); diff --git a/dlls/d3dx9_36/volume.c b/dlls/d3dx9_36/volume.c index 4d29cfe1e31..a99e9d03b58 100644 --- a/dlls/d3dx9_36/volume.c +++ b/dlls/d3dx9_36/volume.c @@ -71,16 +71,29 @@ HRESULT WINAPI D3DXLoadVolumeFromFileW(IDirect3DVolume9 *dst_volume, const PALET return hr; }
+static void set_d3dbox(D3DBOX *box, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, uint32_t front, + uint32_t back) +{ + box->Left = left; + box->Top = top; + box->Right = right; + box->Bottom = bottom; + box->Front = front; + box->Back = back; +} + HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *dst_palette, const D3DBOX *dst_box, const void *src_memory, D3DFORMAT src_format, UINT src_row_pitch, UINT src_slice_pitch, const PALETTEENTRY *src_palette, const D3DBOX *src_box, DWORD filter, D3DCOLOR color_key) { - HRESULT hr; - D3DVOLUME_DESC desc; - D3DLOCKED_BOX locked_box; - struct volume dst_size, src_size; const struct pixel_format_desc *src_format_desc, *dst_format_desc; + struct d3dx_pixels src_pixels, dst_pixels; + D3DBOX dst_box_aligned, dst_box_tmp; + D3DLOCKED_BOX locked_box; + RECT dst_rect_aligned; + D3DVOLUME_DESC desc; + HRESULT hr;
TRACE("dst_volume %p, dst_palette %p, dst_box %p, src_memory %p, src_format %#x, " "src_row_pitch %u, src_slice_pitch %u, src_palette %p, src_box %p, filter %#lx, color_key 0x%08lx.\n", @@ -98,17 +111,19 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, if (filter == D3DX_DEFAULT) filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
- IDirect3DVolume9_GetDesc(dst_volume, &desc); + src_format_desc = get_format_info(src_format); + if (src_format_desc->type == FORMAT_UNKNOWN) + return E_NOTIMPL;
- src_size.width = src_box->Right - src_box->Left; - src_size.height = src_box->Bottom - src_box->Top; - src_size.depth = src_box->Back - src_box->Front; + IDirect3DVolume9_GetDesc(dst_volume, &desc); + dst_format_desc = get_format_info(desc.Format); + if (dst_format_desc->type == FORMAT_UNKNOWN) + return E_NOTIMPL;
if (!dst_box) { - dst_size.width = desc.Width; - dst_size.height = desc.Height; - dst_size.depth = desc.Depth; + set_d3dbox(&dst_box_tmp, 0, 0, desc.Width, desc.Height, 0, desc.Depth); + dst_box = &dst_box_tmp; } else { @@ -118,94 +133,37 @@ HRESULT WINAPI D3DXLoadVolumeFromMemory(IDirect3DVolume9 *dst_volume, return D3DERR_INVALIDCALL; if (dst_box->Front >= dst_box->Back || dst_box->Back > desc.Depth) return D3DERR_INVALIDCALL; - - dst_size.width = dst_box->Right - dst_box->Left; - dst_size.height = dst_box->Bottom - dst_box->Top; - dst_size.depth = dst_box->Back - dst_box->Front; }
- src_format_desc = get_format_info(src_format); - if (src_format_desc->type == FORMAT_UNKNOWN) - return E_NOTIMPL; + hr = d3dx_pixels_init(src_memory, src_row_pitch, src_slice_pitch, + src_palette, src_format, src_box->Left, src_box->Top, src_box->Right, src_box->Bottom, + src_box->Front, src_box->Back, &src_pixels); + if (FAILED(hr)) + return hr;
- dst_format_desc = get_format_info(desc.Format); - if (dst_format_desc->type == FORMAT_UNKNOWN) - return E_NOTIMPL; + get_aligned_rect(dst_box->Left, dst_box->Top, dst_box->Right, dst_box->Bottom, desc.Width, desc.Height, + dst_format_desc, &dst_rect_aligned); + set_d3dbox(&dst_box_aligned, dst_rect_aligned.left, dst_rect_aligned.top, dst_rect_aligned.right, + dst_rect_aligned.bottom, dst_box->Front, dst_box->Back);
- if (desc.Format == src_format - && dst_size.width == src_size.width - && dst_size.height == src_size.height - && dst_size.depth == src_size.depth - && color_key == 0) - { - const BYTE *src_addr; - - if (src_box->Left & (src_format_desc->block_width - 1) - || src_box->Top & (src_format_desc->block_height - 1) - || (src_box->Right & (src_format_desc->block_width - 1) - && src_size.width != desc.Width) - || (src_box->Bottom & (src_format_desc->block_height - 1) - && src_size.height != desc.Height)) - { - FIXME("Source box (%u, %u, %u, %u) is misaligned\n", - src_box->Left, src_box->Top, src_box->Right, src_box->Bottom); - return E_NOTIMPL; - } - - src_addr = src_memory; - src_addr += src_box->Front * src_slice_pitch; - src_addr += (src_box->Top / src_format_desc->block_height) * src_row_pitch; - src_addr += (src_box->Left / src_format_desc->block_width) * src_format_desc->block_byte_count; - - hr = IDirect3DVolume9_LockBox(dst_volume, &locked_box, dst_box, 0); - if (FAILED(hr)) return hr; - - copy_pixels(src_addr, src_row_pitch, src_slice_pitch, - locked_box.pBits, locked_box.RowPitch, locked_box.SlicePitch, - &dst_size, dst_format_desc); - - IDirect3DVolume9_UnlockBox(dst_volume); - } - else - { - const BYTE *src_addr; - - if (!is_conversion_from_supported(src_format_desc) - || !is_conversion_to_supported(dst_format_desc)) - { - FIXME("Pixel format conversion is not implemented %#x -> %#x\n", - src_format_desc->format, dst_format_desc->format); - return E_NOTIMPL; - } - - src_addr = src_memory; - src_addr += src_box->Front * src_slice_pitch; - src_addr += src_box->Top * src_row_pitch; - src_addr += src_box->Left * src_format_desc->bytes_per_pixel; - - hr = IDirect3DVolume9_LockBox(dst_volume, &locked_box, dst_box, 0); - if (FAILED(hr)) return hr; - - if ((filter & 0xf) == D3DX_FILTER_NONE) - { - convert_argb_pixels(src_memory, src_row_pitch, src_slice_pitch, &src_size, src_format_desc, - locked_box.pBits, locked_box.RowPitch, locked_box.SlicePitch, &dst_size, dst_format_desc, color_key, - src_palette); - } - else - { - if ((filter & 0xf) != D3DX_FILTER_POINT) - FIXME("Unhandled filter %#lx.\n", filter); - - point_filter_argb_pixels(src_addr, src_row_pitch, src_slice_pitch, &src_size, src_format_desc, - locked_box.pBits, locked_box.RowPitch, locked_box.SlicePitch, &dst_size, dst_format_desc, color_key, - src_palette); - } - - IDirect3DVolume9_UnlockBox(dst_volume); - } + hr = IDirect3DVolume9_LockBox(dst_volume, &locked_box, &dst_box_aligned, 0); + if (FAILED(hr)) + return hr;
- return D3D_OK; + dst_pixels.data = locked_box.pBits; + dst_pixels.row_pitch = locked_box.RowPitch; + dst_pixels.slice_pitch = locked_box.SlicePitch; + dst_pixels.palette = dst_palette; + dst_pixels.width = dst_box_aligned.Right - dst_box_aligned.Left; + dst_pixels.height = dst_box_aligned.Bottom - dst_box_aligned.Top; + dst_pixels.depth = dst_box_aligned.Back - dst_box_aligned.Front; + SetRect(&dst_pixels.unaligned_rect, dst_box->Left, dst_box->Top, dst_box->Right, dst_box->Bottom); + OffsetRect(&dst_pixels.unaligned_rect, -dst_rect_aligned.left, -dst_rect_aligned.top); + + hr = d3dx_load_pixels_from_pixels(&dst_pixels, dst_format_desc, &src_pixels, src_format_desc, filter, + color_key); + IDirect3DVolume9_UnlockBox(dst_volume); + return hr; }
HRESULT WINAPI D3DXLoadVolumeFromFileInMemory(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *dst_palette,
On Sun May 26 12:43:21 2024 +0000, Connor McAdams wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/5666/diffs?diff_id=115190&start_sha=04c51c5eac6f69386870f2ea96e616838cda38be#8fffeae09861a99974e55842964630933974cdc8_2030_1983)
Switched to ptr.
On Sun May 26 12:43:21 2024 +0000, Connor McAdams wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/5666/diffs?diff_id=115190&start_sha=04c51c5eac6f69386870f2ea96e616838cda38be#8fffeae09861a99974e55842964630933974cdc8_2027_1978)
The reason for the int/uint mix is because some of the functions calling this are pulling those values from a `RECT` structure which contains signed ints. I wrote this under the assumption that negative values in e.g the source rectangle argument `D3DXLoadSurfaceFromMemory` were expected to work, but after writing tests it seems like that's more of an unintended thing that only works on 32-bit. I've switched them all to uints in the most recent revision.
Initially I did pack these into a box structure, but that started to feel a bit messy to me, in particular because there were 3 different types of structures in use (`RECT` for d3d9 surfaces, `D3DBOX` for d3d9 volumes, and then `D3D10_BOX`/`D3D11_BOX` for d3d10/d3d11. Rather than add a call to pack a structure before each `d3dx_pixels_init` call, I figured it'd make more sense to just have the values as arguments instead. I can change that if you'd like. :)
On Sun May 26 12:43:22 2024 +0000, Connor McAdams wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/5666/diffs?diff_id=115190&start_sha=04c51c5eac6f69386870f2ea96e616838cda38be#8fffeae09861a99974e55842964630933974cdc8_2373_2313)
I've changed this now to print the errors inside of `d3dx_load_pixels_from_pixels()` instead.
On Sun May 26 12:43:23 2024 +0000, Connor McAdams wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/5666/diffs?diff_id=115190&start_sha=04c51c5eac6f69386870f2ea96e616838cda38be#e5891b30c0f0a0d106394089d61a67281f349564_92_84)
I've moved away from the callback system now, so this shouldn't matter anymore. :)
On Sun May 26 12:43:24 2024 +0000, Connor McAdams wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/5666/diffs?diff_id=115190&start_sha=04c51c5eac6f69386870f2ea96e616838cda38be#e5891b30c0f0a0d106394089d61a67281f349564_76_71)
I've changed this to `struct d3dx_pixels`, does this seem better?
On Sun May 26 12:54:18 2024 +0000, Matteo Bruni wrote:
Maybe we could have a small comment here clarifying that image_buf is non-NULL iff struct d3dx_image_resource has ownership of image data that needs to be released afterwards.
Added in the most recent patch set.
On Wed May 22 12:36:18 2024 +0000, Matteo Bruni wrote:
Right. I think it would be nice to have this (or the same on an equivalent, private, struct) in the generic helpers. FWIW, the name `set_d3dbox()` looks fine here, because the function works on a simple, small structure that you wouldn't necessarily expect to be initialized only once.
Is this fine where it is, or by mentioning the generic helpers do you mean it should exist somewhere else in the code? I mainly put it here since it's only used in this source file, but I can move it if that'd make sense.
On Sun May 26 12:43:24 2024 +0000, Connor McAdams wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/5666/diffs?diff_id=115190&start_sha=04c51c5eac6f69386870f2ea96e616838cda38be#e5891b30c0f0a0d106394089d61a67281f349564_111_94)
Yeah in hindsight I think I might have been trying to make things more generic than was necessary. I've spent some time mapping it out and I think it can be done without callbacks. It might lead to some loop duplication, but I don't think that's the worst thing, and it will probably make the code clearer.
I've changed things around in the current revision, let me know what you think. :)
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/surface.c:
- hr = IWICStream_InitializeFromMemory(wic_stream, (BYTE *)src_image, src_image_size);
- if (FAILED(hr))
goto exit;
- hr = IWICImagingFactory_CreateDecoderFromStream(wic_factory, (IStream *)wic_stream, NULL, 0, &bitmap_decoder);
- if (FAILED(hr))
- {
if ((src_image_size >= 2) && (!strncmp(src_image, "P3", 2) || !strncmp(src_image, "P6", 2)))
FIXME("File type PPM is not supported yet.\n");
else if ((src_image_size >= 10) && !strncmp(src_image, "#?RADIANCE", 10))
FIXME("File type HDR is not supported yet.\n");
else if ((src_image_size >= 2) && (!strncmp(src_image, "PF", 2) || !strncmp(src_image, "Pf", 2)))
FIXME("File type PFM is not supported yet.\n");
goto exit;
- }
This is just moving old code around but I think we can make some improvements while at it. Here it looks like we can replace those `strncmp()` uses with `memcmp()`.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/surface.c:
else if ((src_image_size >= 10) && !strncmp(src_image, "#?RADIANCE", 10))
FIXME("File type HDR is not supported yet.\n");
else if ((src_image_size >= 2) && (!strncmp(src_image, "PF", 2) || !strncmp(src_image, "Pf", 2)))
FIXME("File type PFM is not supported yet.\n");
goto exit;
- }
- hr = IWICBitmapDecoder_GetContainerFormat(bitmap_decoder, &container_format);
- if (FAILED(hr))
goto exit;
- info->ImageFileFormat = wic_container_guid_to_d3dx_file_format(&container_format);
- if (is_dib && info->ImageFileFormat == D3DXIFF_BMP)
info->ImageFileFormat = D3DXIFF_DIB;
- else if (info->ImageFileFormat == D3DXIFF_FORCE_DWORD)
- {
Style comment, usually we prefer to have `{` `}` on both branches of an `if` when you need them for one anyway.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/surface.c:
- if (image_is_argb(bitmap_frame, info))
info->Format = D3DFMT_A8R8G8B8;
- info->Depth = 1;
- info->MipLevels = 1;
- info->ResourceType = D3DRTYPE_TEXTURE;
+exit:
- if (is_dib) free((void *)src_image);
- if (wic_factory) IWICImagingFactory_Release(wic_factory);
- if (wic_stream) IWICStream_Release(wic_stream);
- if (bitmap_decoder) IWICBitmapDecoder_Release(bitmap_decoder);
- if (bitmap_frame) IWICBitmapFrameDecode_Release(bitmap_frame);
- return hr;
+}
More general style comments: - we usually put the "release" calls in reverse order of allocation - `if ()` body on its own line
BTW, definitely moving all the cleanup at the end of the function makes for nicer code, I approve :thumbsup:
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/surface.c:
- TRACE("Pixel format is %#x.\n", image->format);
- if (header->caps2 & DDS_CAPS2_VOLUME)
- {
image->depth = header->depth;
image->resource_type = D3DRTYPE_VOLUMETEXTURE;
- }
- else if (header->caps2 & DDS_CAPS2_CUBEMAP)
- {
DWORD face;
faces = 0;
for (face = DDS_CAPS2_CUBEMAP_POSITIVEX; face <= DDS_CAPS2_CUBEMAP_NEGATIVEZ; face <<= 1)
{
if (header->caps2 & face)
faces++;
}
This could be replaced by a `popcount(header->caps2 & DDS_CAPS2_CUBEMAP_ALL_FACES)`, except it's probably not worth it just for this one use. We apparently can't depend on the builtin (we have multiple wrappers in Wine) and either adding one more implementation here or factoring out one of the existing ones seems overkill.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/surface.c:
}
}
+static HRESULT d3dx_image_wic_frame_decode(struct d3dx_image *image,
IWICImagingFactory *wic_factory, IWICBitmapFrameDecode *bitmap_frame)
+{
- const struct pixel_format_desc *fmt_desc;
- uint32_t row_pitch, slice_pitch;
- IWICPalette *wic_palette = NULL;
- PALETTEENTRY *palette = NULL;
- WICColor *colors = NULL;
- BYTE *buffer = NULL;
- HRESULT hr;
- fmt_desc = get_format_info(image->format);
- hr = calculate_dds_surface_size(image->format, image->width, image->height, &row_pitch, &slice_pitch);
Worth considering whether to rename this function, now that it's used outside of DDS loading / saving (the function has nothing DDS-specific anyway).
On Wed May 29 23:53:27 2024 +0000, Connor McAdams wrote:
The reason for the int/uint mix is because some of the functions calling this are pulling those values from a `RECT` structure which contains signed ints. I wrote this under the assumption that negative values in e.g the source rectangle argument `D3DXLoadSurfaceFromMemory` were expected to work, but after writing tests it seems like that's more of an unintended thing that only works on 32-bit. I've switched them all to uints in the most recent revision. Initially I did pack these into a box structure, but that started to feel a bit messy to me, in particular because there were 3 different types of structures in use (`RECT` for d3d9 surfaces, `D3DBOX` for d3d9 volumes, and then `D3D10_BOX`/`D3D11_BOX` for d3d10/d3d11. Rather than add a call to pack a structure before each `d3dx_pixels_init` call, I figured it'd make more sense to just have the values as arguments instead. I can change that if you'd like. :)
No, this is certainly fine. I was kind of hoping that packing here would eventually avoid packing afterwards (i.e. it would have been just a matter of moving some pack calls around) but, indeed, it doesn't seem to be the case.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/surface.c:
- dst_locked_rect = *dst_rect;
- OffsetRect(&dst_locked_rect_aligned, -dst_rect_aligned.left, -dst_rect_aligned.top);
- OffsetRect(&dst_locked_rect, -dst_rect_aligned.left, -dst_rect_aligned.top);
- hr = d3dx_load_image_from_memory(lockrect.pBits, lockrect.Pitch, destformatdesc, dst_palette, &dst_locked_rect,
&dst_locked_rect_aligned, src_memory, src_pitch, srcformatdesc, src_palette, src_rect, filter, color_key);
- if (FAILED(hr))
WARN("d3dx_load_image_from_memory failed with hr %#lx\n", hr);
- dst_pixels.data = lockrect.pBits;
- dst_pixels.row_pitch = lockrect.Pitch;
- dst_pixels.slice_pitch = 0;
- dst_pixels.palette = dst_palette;
- dst_pixels.width = dst_rect_aligned.right - dst_rect_aligned.left;
- dst_pixels.height = dst_rect_aligned.bottom - dst_rect_aligned.top;
- dst_pixels.depth = 1;
- dst_pixels.unaligned_rect = *dst_rect;
- OffsetRect(&dst_pixels.unaligned_rect, -dst_rect_aligned.left, -dst_rect_aligned.top);
Would it make sense to use `d3dx_pixels_init()` here?
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/surface.c:
return E_NOTIMPL; }
- if (!(uncompressed_mem = malloc(size->width * size->height * size->depth * uncompressed_desc->bytes_per_pixel)))
- if (!(uncompressed_mem = malloc(pixels->width * pixels->height * pixels->depth * uncompressed_desc->bytes_per_pixel)))
I don't mean to cause unnecessary churn but maybe embedding a `struct volume` inside `struct d3dx_pixels` would be nice?
Feel 100% free to dismiss this one.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/surface.c:
{
uint32_t uncompressed_row_pitch, uncompressed_slice_pitch; const struct pixel_format_desc *uncompressed_desc;
uint32_t uncompressed_row_pitch; void *uncompressed_mem = NULL; hr = d3dx_pixels_decompress(src_pixels, src_desc, FALSE, &uncompressed_mem, &uncompressed_row_pitch,
&uncompressed_desc);
&uncompressed_slice_pitch, &uncompressed_desc); if (SUCCEEDED(hr)) { struct d3dx_pixels uncompressed_pixels;
d3dx_pixels_init((const void *)uncompressed_mem, uncompressed_row_pitch, 0, NULL, uncompressed_desc->format,
0, 0, src_pixels->width, src_pixels->height, 0, src_pixels->depth, &uncompressed_pixels);
d3dx_pixels_init((const void *)uncompressed_mem, uncompressed_row_pitch,
That cast shouldn't be necessary.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/surface.c:
uint32_t uncompressed_row_pitch, uncompressed_slice_pitch; const struct pixel_format_desc *uncompressed_desc; struct d3dx_pixels uncompressed_pixels;
uint32_t uncompressed_row_pitch; void *uncompressed_mem = NULL; hr = d3dx_pixels_decompress(dst_pixels, dst_desc, TRUE, &uncompressed_mem, &uncompressed_row_pitch,
&uncompressed_desc);
&uncompressed_slice_pitch, &uncompressed_desc); if (FAILED(hr)) goto exit;
d3dx_pixels_init((const void *)uncompressed_mem, uncompressed_row_pitch, 0, NULL,
uncompressed_desc->format, dst_pixels->unaligned_rect.left, dst_pixels->unaligned_rect.top,
dst_pixels->unaligned_rect.right, dst_pixels->unaligned_rect.bottom, 0, 1, &uncompressed_pixels);
d3dx_pixels_init((const void *)uncompressed_mem, uncompressed_row_pitch,
Same here.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/surface.c:
}
+void get_aligned_rect(uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, uint32_t width, uint32_t height,
const struct pixel_format_desc *fmt_desc, RECT *aligned_rect)
+{
- SetRect(aligned_rect, left, top, right, bottom);
- if (aligned_rect->left & (fmt_desc->block_width - 1))
aligned_rect->left = aligned_rect->left & ~(fmt_desc->block_width - 1);
- if (aligned_rect->top & (fmt_desc->block_height - 1))
aligned_rect->top = aligned_rect->top & ~(fmt_desc->block_height - 1);
- if (aligned_rect->right & (fmt_desc->block_width - 1) && aligned_rect->right != width)
aligned_rect->right = min((aligned_rect->right + fmt_desc->block_width - 1)
& ~(fmt_desc->block_width - 1), width);
- if (aligned_rect->bottom & (fmt_desc->block_height - 1) && aligned_rect->bottom != height)
aligned_rect->bottom = min((aligned_rect->bottom + fmt_desc->block_height - 1)
& ~(fmt_desc->block_height - 1), height);
I realize this is my own code (which I kind of hate right now :sweat_smile:), but do you happen to know a practical case where these `min()` are needed? I suspect they are effectively unnecessary, but also not something that this MR should care about.
On Wed May 29 23:53:29 2024 +0000, Connor McAdams wrote:
Yeah in hindsight I think I might have been trying to make things more generic than was necessary. I've spent some time mapping it out and I think it can be done without callbacks. It might lead to some loop duplication, but I don't think that's the worst thing, and it will probably make the code clearer. I've changed things around in the current revision, let me know what you think. :)
I'm guilty of over-complicating things myself. Also, often the easier route becomes clear only after the fact :slight_smile:
I guess the most interesting bits are still down the road, but it does look nicer for now. And yes, I feel like it's going to be a net positive if it's just a matter of duplicating a few simple loops. Feel free to push back if it starts to turn into a mess, though.
On Wed May 29 23:53:30 2024 +0000, Connor McAdams wrote:
Is this fine where it is, or by mentioning the generic helpers do you mean it should exist somewhere else in the code? I mainly put it here since it's only used in this source file, but I can move it if that'd make sense.
I think this comment was in the context of packing the bounds passed to `set_d3dx_sub_resource_from_memory()`, where we could have used something like this as a helper if we went for that route. So this is moot now, I think.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/volume.c:
IDirect3DVolume9_UnlockBox(dst_volume);
- }
- hr = IDirect3DVolume9_LockBox(dst_volume, &locked_box, &dst_box_aligned, 0);
- if (FAILED(hr))
return hr;
- return D3D_OK;
- dst_pixels.data = locked_box.pBits;
- dst_pixels.row_pitch = locked_box.RowPitch;
- dst_pixels.slice_pitch = locked_box.SlicePitch;
- dst_pixels.palette = dst_palette;
- dst_pixels.width = dst_box_aligned.Right - dst_box_aligned.Left;
- dst_pixels.height = dst_box_aligned.Bottom - dst_box_aligned.Top;
- dst_pixels.depth = dst_box_aligned.Back - dst_box_aligned.Front;
- SetRect(&dst_pixels.unaligned_rect, dst_box->Left, dst_box->Top, dst_box->Right, dst_box->Bottom);
- OffsetRect(&dst_pixels.unaligned_rect, -dst_rect_aligned.left, -dst_rect_aligned.top);
Same as for `D3DXLoadSurfaceFromMemory()`, can we use `d3dx_pixels_init()` here?
I've left some minor comments, ~half of which don't require changes. It looks pretty good to me now.