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. :)
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 | 191 +++++++++++++++++++++------------------- 1 file changed, 101 insertions(+), 90 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index bf9096e3ec5..1420b4d6ebe 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -976,6 +976,105 @@ 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; + IWICPalette *wic_palette = NULL; + 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)) + goto exit; + + 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); + if (wic_palette) IWICPalette_Release(wic_palette); + + return hr; +} + /************************************************************ * D3DXGetImageInfoFromFileInMemory * @@ -999,11 +1098,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 +1111,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 | 32 +++++ dlls/d3dx9_36/surface.c | 231 ++++++++++++++++++++-------------- 2 files changed, 166 insertions(+), 97 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 668fbb27b28..1d4fd2e3125 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -68,6 +68,38 @@ struct pixel_format_desc { void (*to_rgba)(const struct vec4 *src, struct vec4 *dst, const PALETTEENTRY *palette); };
+enum d3dx_resource_type +{ + D3DX_RESOURCE_TYPE_IMAGE = 1, +}; + +struct d3dx_resource; +struct d3dx_resource_ops +{ + void (__stdcall *d3dx_resource_release)(struct d3dx_resource *resource); +}; + +#define d3dx_resource_release(resource) (resource)->resource_ops->d3dx_resource_release(resource) +struct d3dx_resource +{ + const struct d3dx_resource_ops *resource_ops; + enum d3dx_resource_type d3dx_resource_type; + D3DRESOURCETYPE resource_type; + D3DFORMAT format; + + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t mip_levels; +}; + +struct d3dx_image_resource +{ + struct d3dx_resource resource; + + 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 1420b4d6ebe..c2e81358289 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -24,6 +24,7 @@ #include "initguid.h" #include "ole2.h" #include "wincodec.h" +#include <assert.h>
#include "txc_dxtn.h"
@@ -481,78 +482,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 +751,79 @@ HRESULT load_volume_texture_from_dds(IDirect3DVolumeTexture9 *volume_texture, co return D3D_OK; }
+static inline struct d3dx_image_resource *d3dx_image_resource_from_resource(struct d3dx_resource *resource) +{ + assert(resource->d3dx_resource_type == D3DX_RESOURCE_TYPE_IMAGE); + return CONTAINING_RECORD(resource, struct d3dx_image_resource, resource); +} + +static void __stdcall d3dx_image_resource_release(struct d3dx_resource *resource) +{ + struct d3dx_image_resource *image_resource = d3dx_image_resource_from_resource(resource); + + TRACE("image_resource %p.\n", image_resource); + free(image_resource); +} + +static const struct d3dx_resource_ops image_resource_ops = +{ + d3dx_image_resource_release, +}; + +static HRESULT d3dx_initialize_image_resource_from_dds(const void *src_data, uint32_t src_data_size, + struct d3dx_image_resource *image_resource) +{ + struct d3dx_resource *resource = &image_resource->resource; + 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"); + resource->width = header->width; + resource->height = header->height; + resource->depth = 1; + resource->mip_levels = header->miplevels ? header->miplevels : 1; + resource->format = dds_pixel_format_to_d3dformat(&header->pixel_format); + + if (resource->format == D3DFMT_UNKNOWN) + return D3DXERR_INVALIDDATA; + + TRACE("Pixel format is %#x.\n", resource->format); + if (header->caps2 & DDS_CAPS2_VOLUME) + { + resource->depth = header->depth; + resource->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++; + } + resource->resource_type = D3DRTYPE_CUBETEXTURE; + } + else + resource->resource_type = D3DRTYPE_TEXTURE; + + expected_src_data_size = calculate_dds_file_size(resource->format, resource->width, resource->height, + resource->depth, resource->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_resource->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 +891,29 @@ 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_resource *image_resource) { + struct d3dx_resource *resource = &image_resource->resource; unsigned int size, i; BYTE *buffer; HRESULT hr;
- if (info->Format != D3DFMT_X8R8G8B8 || (info->ImageFileFormat != D3DXIFF_BMP - && info->ImageFileFormat != D3DXIFF_TGA)) + if (resource->format != D3DFMT_X8R8G8B8 || (image_resource->image_file_format != D3DXIFF_BMP + && image_resource->image_file_format != D3DXIFF_TGA)) return FALSE;
- size = info->Width * info->Height * 4; + size = resource->width * resource->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, resource->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 < resource->width * resource->height; ++i) { if (buffer[i * 4 + 3]) { @@ -976,8 +979,10 @@ 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_resource_from_wic(const void *src_data, uint32_t src_data_size, + struct d3dx_image_resource *image_resource) { + struct d3dx_resource *resource = &image_resource->resource; IWICBitmapFrameDecode *bitmap_frame = NULL; IWICBitmapDecoder *bitmap_decoder = NULL; uint32_t src_image_size = src_data_size; @@ -1020,17 +1025,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_resource->image_file_format = wic_container_guid_to_d3dx_file_format(&container_format); + if (is_dib && image_resource->image_file_format == D3DXIFF_BMP) + image_resource->image_file_format = D3DXIFF_DIB; + else if (image_resource->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_resource->image_file_format)); hr = IWICBitmapDecoder_GetFrameCount(bitmap_decoder, &frame_count); if (FAILED(hr) || (SUCCEEDED(hr) && !frame_count)) { @@ -1042,7 +1047,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, &resource->width, &resource->height); if (FAILED(hr)) goto exit;
@@ -1050,19 +1055,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 ((resource->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_resource)) + resource->format = D3DFMT_A8R8G8B8;
- info->Depth = 1; - info->MipLevels = 1; - info->ResourceType = D3DRTYPE_TEXTURE; + resource->depth = 1; + resource->mip_levels = 1; + resource->resource_type = D3DRTYPE_TEXTURE;
exit: if (is_dib) free((void *)src_image); @@ -1075,6 +1080,33 @@ exit: return hr; }
+static HRESULT d3dx_create_image_resource(const void *src_data, uint32_t src_data_size, + struct d3dx_image_resource **out_resource) +{ + struct d3dx_image_resource *image_resource = NULL; + HRESULT hr; + + if (!src_data || !src_data_size || !out_resource) + return D3DERR_INVALIDCALL; + + *out_resource = NULL; + if (!(image_resource = calloc(1, sizeof(*image_resource)))) + return E_OUTOFMEMORY; + + image_resource->resource.d3dx_resource_type = D3DX_RESOURCE_TYPE_IMAGE; + image_resource->resource.resource_ops = &image_resource_ops; + if ((src_data_size >= 4) && !strncmp(src_data, "DDS ", 4)) + hr = d3dx_initialize_image_resource_from_dds(src_data, src_data_size, image_resource); + else + hr = d3dx_initialize_image_resource_from_wic(src_data, src_data_size, image_resource); + + if (SUCCEEDED(hr)) + *out_resource = image_resource; + + if (FAILED(hr)) d3dx_resource_release(&image_resource->resource); + return hr; +} + /************************************************************ * D3DXGetImageInfoFromFileInMemory * @@ -1098,6 +1130,7 @@ exit: */ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(const void *data, UINT datasize, D3DXIMAGE_INFO *info) { + struct d3dx_image_resource *image_resource; HRESULT hr;
TRACE("(%p, %d, %p)\n", data, datasize, info); @@ -1108,17 +1141,21 @@ 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_create_image_resource(data, datasize, &image_resource); if (FAILED(hr)) { TRACE("Invalid or unsupported image file\n"); return D3DXERR_INVALIDDATA; }
+ info->ImageFileFormat = image_resource->image_file_format; + info->Width = image_resource->resource.width; + info->Height = image_resource->resource.height; + info->Depth = image_resource->resource.depth; + info->MipLevels = image_resource->resource.mip_levels; + info->Format = image_resource->resource.format; + info->ResourceType = image_resource->resource.resource_type; + d3dx_resource_release(&image_resource->resource); + return D3D_OK; }
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/d3dx9_36/d3dx9_private.h | 20 +++ dlls/d3dx9_36/surface.c | 320 +++++++++++++++------------------- 2 files changed, 163 insertions(+), 177 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 1d4fd2e3125..6ffb1e7ae08 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -73,13 +73,29 @@ enum d3dx_resource_type D3DX_RESOURCE_TYPE_IMAGE = 1, };
+struct d3dx_sub_resource +{ + const void *data; + uint32_t row_pitch; + uint32_t slice_pitch; + const PALETTEENTRY *palette; + + uint32_t width; + uint32_t height; + uint32_t depth; +}; + struct d3dx_resource; struct d3dx_resource_ops { void (__stdcall *d3dx_resource_release)(struct d3dx_resource *resource); + HRESULT (__stdcall *d3dx_resource_get_sub_resource)(struct d3dx_resource *resource, + struct d3dx_sub_resource *sub_resource); };
#define d3dx_resource_release(resource) (resource)->resource_ops->d3dx_resource_release(resource) +#define d3dx_resource_get_sub_resource(resource, sub_resource) \ + (resource)->resource_ops->d3dx_resource_get_sub_resource(resource, sub_resource) struct d3dx_resource { const struct d3dx_resource_ops *resource_ops; @@ -93,10 +109,14 @@ struct d3dx_resource uint32_t mip_levels; };
+#define D3DX_IMAGE_RESOURCE_INFO_ONLY 1 struct d3dx_image_resource { struct d3dx_resource resource;
+ BYTE *pixels; + 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 c2e81358289..ebaf347d65f 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -482,25 +482,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; @@ -762,12 +743,39 @@ static void __stdcall d3dx_image_resource_release(struct d3dx_resource *resource struct d3dx_image_resource *image_resource = d3dx_image_resource_from_resource(resource);
TRACE("image_resource %p.\n", image_resource); + free(image_resource->image_buf); + free(image_resource->palette); free(image_resource); }
+static HRESULT __stdcall d3dx_image_resource_get_sub_resource(struct d3dx_resource *resource, + struct d3dx_sub_resource *sub_rsrc) +{ + struct d3dx_image_resource *image_resource = d3dx_image_resource_from_resource(resource); + uint32_t row_pitch, slice_pitch; + HRESULT hr = S_OK; + + TRACE("image_resource %p, sub_rsrc %p.\n", image_resource, sub_rsrc); + + hr = calculate_dds_surface_size(resource->format, resource->width, resource->height, &row_pitch, &slice_pitch); + if (FAILED(hr)) + return hr; + + sub_rsrc->data = image_resource->pixels; + sub_rsrc->row_pitch = row_pitch; + sub_rsrc->slice_pitch = slice_pitch; + sub_rsrc->palette = image_resource->palette; + sub_rsrc->width = resource->width; + sub_rsrc->height = resource->height; + sub_rsrc->depth = resource->depth; + + return hr; +} + static const struct d3dx_resource_ops image_resource_ops = { d3dx_image_resource_release, + d3dx_image_resource_get_sub_resource, };
static HRESULT d3dx_initialize_image_resource_from_dds(const void *src_data, uint32_t src_data_size, @@ -820,6 +828,7 @@ static HRESULT d3dx_initialize_image_resource_from_dds(const void *src_data, uin return D3DXERR_INVALIDDATA; }
+ image_resource->pixels = ((BYTE *)src_data) + sizeof(*header); image_resource->image_file_format = D3DXIFF_DDS; return D3D_OK; } @@ -979,8 +988,82 @@ static const char *debug_d3dx_image_file_format(D3DXIMAGE_FILEFORMAT format) } }
+static HRESULT d3dx_image_resource_wic_frame_decode(struct d3dx_image_resource *image_resource, + IWICImagingFactory *wic_factory, IWICBitmapFrameDecode *bitmap_frame) +{ + struct d3dx_resource *resource = &image_resource->resource; + 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(resource->format); + hr = calculate_dds_surface_size(resource->format, resource->width, resource->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_resource->image_buf = image_resource->pixels = buffer; + image_resource->palette = palette; + +exit: + free(colors); + if (image_resource->image_buf != buffer) free(buffer); + if (image_resource->palette != palette) free(palette); + if (wic_palette) IWICPalette_Release(wic_palette); + + return hr; +} + static HRESULT d3dx_initialize_image_resource_from_wic(const void *src_data, uint32_t src_data_size, - struct d3dx_image_resource *image_resource) + struct d3dx_image_resource *image_resource, uint32_t flags) { struct d3dx_resource *resource = &image_resource->resource; IWICBitmapFrameDecode *bitmap_frame = NULL; @@ -1065,6 +1148,13 @@ static HRESULT d3dx_initialize_image_resource_from_wic(const void *src_data, uin if (image_is_argb(bitmap_frame, image_resource)) resource->format = D3DFMT_A8R8G8B8;
+ if (!(flags & D3DX_IMAGE_RESOURCE_INFO_ONLY)) + { + hr = d3dx_image_resource_wic_frame_decode(image_resource, wic_factory, bitmap_frame); + if (FAILED(hr)) + goto exit; + } + resource->depth = 1; resource->mip_levels = 1; resource->resource_type = D3DRTYPE_TEXTURE; @@ -1081,7 +1171,7 @@ exit: }
static HRESULT d3dx_create_image_resource(const void *src_data, uint32_t src_data_size, - struct d3dx_image_resource **out_resource) + struct d3dx_image_resource **out_resource, uint32_t flags) { struct d3dx_image_resource *image_resource = NULL; HRESULT hr; @@ -1098,7 +1188,7 @@ static HRESULT d3dx_create_image_resource(const void *src_data, uint32_t src_dat if ((src_data_size >= 4) && !strncmp(src_data, "DDS ", 4)) hr = d3dx_initialize_image_resource_from_dds(src_data, src_data_size, image_resource); else - hr = d3dx_initialize_image_resource_from_wic(src_data, src_data_size, image_resource); + hr = d3dx_initialize_image_resource_from_wic(src_data, src_data_size, image_resource, flags);
if (SUCCEEDED(hr)) *out_resource = image_resource; @@ -1107,6 +1197,17 @@ static HRESULT d3dx_create_image_resource(const void *src_data, uint32_t src_dat return hr; }
+static void d3dximage_info_from_d3dx_image_resource(D3DXIMAGE_INFO *info, struct d3dx_image_resource *image_resource) +{ + info->ImageFileFormat = image_resource->image_file_format; + info->Width = image_resource->resource.width; + info->Height = image_resource->resource.height; + info->Depth = image_resource->resource.depth; + info->MipLevels = image_resource->resource.mip_levels; + info->Format = image_resource->resource.format; + info->ResourceType = image_resource->resource.resource_type; +} + /************************************************************ * D3DXGetImageInfoFromFileInMemory * @@ -1141,19 +1242,13 @@ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(const void *data, UINT datasize, if (!info) return D3D_OK;
- hr = d3dx_create_image_resource(data, datasize, &image_resource); + hr = d3dx_create_image_resource(data, datasize, &image_resource, D3DX_IMAGE_RESOURCE_INFO_ONLY); if (FAILED(hr)) { TRACE("Invalid or unsupported image file\n"); return D3DXERR_INVALIDDATA; }
- info->ImageFileFormat = image_resource->image_file_format; - info->Width = image_resource->resource.width; - info->Height = image_resource->resource.height; - info->Depth = image_resource->resource.depth; - info->MipLevels = image_resource->resource.mip_levels; - info->Format = image_resource->resource.format; - info->ResourceType = image_resource->resource.resource_type; + d3dximage_info_from_d3dx_image_resource(info, image_resource); d3dx_resource_release(&image_resource->resource);
return D3D_OK; @@ -1284,18 +1379,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_sub_resource sub_resource = { 0 }; + struct d3dx_image_resource *image_resource; + 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, @@ -1304,151 +1393,28 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface, if (!pDestSurface || !pSrcData || !SrcDataSize) return D3DERR_INVALIDCALL;
- hr = D3DXGetImageInfoFromFileInMemory(pSrcData, SrcDataSize, &imginfo); - + hr = d3dx_create_image_resource(pSrcData, SrcDataSize, &image_resource, 0); if (FAILED(hr)) - return hr; + return D3DXERR_INVALIDDATA;
+ d3dximage_info_from_d3dx_image_resource(&img_info, image_resource); 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_resource_get_sub_resource(&image_resource->resource, &sub_resource); 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, sub_resource.data, img_info.Format, + sub_resource.row_pitch, sub_resource.palette, &src_rect, dwFilter, Colorkey); + if (SUCCEEDED(hr) && pSrcInfo) + *pSrcInfo = img_info;
- return D3D_OK; +exit: + d3dx_resource_release(&image_resource->resource); + return FAILED(hr) ? D3DXERR_INVALIDDATA : hr; }
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, 127 insertions(+), 46 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 6ffb1e7ae08..4fc755338df 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -83,6 +83,7 @@ struct d3dx_sub_resource uint32_t width; uint32_t height; uint32_t depth; + RECT unaligned_rect; };
struct d3dx_resource; diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index ebaf347d65f..e2106f4b110 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -768,6 +768,7 @@ static HRESULT __stdcall d3dx_image_resource_get_sub_resource(struct d3dx_resour sub_rsrc->width = resource->width; sub_rsrc->height = resource->height; sub_rsrc->depth = resource->depth; + SetRect(&sub_rsrc->unaligned_rect, 0, 0, sub_rsrc->width, sub_rsrc->height);
return hr; } @@ -1995,6 +1996,49 @@ exit: return S_OK; }
+/* + * Pack a d3dx_sub_resource structure for an image in memory, offsetting the + * base address if necessary. + */ +static HRESULT set_d3dx_sub_resource_from_memory(const void *data, uint32_t row_pitch, uint32_t slice_pitch, + const PALETTEENTRY *palette, D3DFORMAT format, int32_t left, int32_t top, int32_t right, int32_t bottom, + uint32_t front, uint32_t back, struct d3dx_sub_resource *sub_rsrc) +{ + const struct pixel_format_desc *fmt_desc = get_format_info(format); + const BYTE *data_offset = data; + + memset(sub_rsrc, 0, sizeof(*sub_rsrc)); + if (fmt_desc->type == FORMAT_UNKNOWN) + { + FIXME("Unsupported format %#x.\n", format); + return E_NOTIMPL; + } + + data_offset += front * slice_pitch; + data_offset += (top / fmt_desc->block_height) * row_pitch; + data_offset += (left / fmt_desc->block_width) * fmt_desc->block_byte_count; + + sub_rsrc->data = data_offset; + sub_rsrc->row_pitch = row_pitch; + sub_rsrc->slice_pitch = slice_pitch; + sub_rsrc->palette = palette; + sub_rsrc->width = right - left; + sub_rsrc->height = bottom - top; + sub_rsrc->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(&sub_rsrc->unaligned_rect, left, top, right, bottom); + OffsetRect(&sub_rsrc->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; @@ -2002,40 +2046,51 @@ 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_sub_resource(struct d3dx_sub_resource *sub_rsrc) +{ + if (!sub_rsrc) 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", sub_rsrc->data, sub_rsrc->row_pitch, sub_rsrc->slice_pitch, sub_rsrc->palette, + sub_rsrc->width, sub_rsrc->height, sub_rsrc->depth, wine_dbgstr_rect(&sub_rsrc->unaligned_rect)); +} + +static HRESULT d3dx_load_sub_resource_from_sub_resource(struct d3dx_sub_resource *dst_sub_rsrc, + const struct pixel_format_desc *dst_desc, struct d3dx_sub_resource *src_sub_rsrc, + 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_sub_rsrc %s, dst_desc %p, src_sub_rsrc %s, src_desc %p, filter_flags %#x, color_key %#x.\n", + debug_d3dx_sub_resource(dst_sub_rsrc), dst_desc, debug_d3dx_sub_resource(src_sub_rsrc), 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_sub_rsrc->unaligned_rect.right - src_sub_rsrc->unaligned_rect.left), + (src_sub_rsrc->unaligned_rect.bottom - src_sub_rsrc->unaligned_rect.top), src_sub_rsrc->depth); + else + set_volume_struct(&src_size, src_sub_rsrc->width, src_sub_rsrc->height, src_sub_rsrc->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_sub_rsrc->width, dst_sub_rsrc->height, dst_sub_rsrc->depth); + if (dst_desc->type == FORMAT_DXT) + set_volume_struct(&dst_size, (dst_sub_rsrc->unaligned_rect.right - dst_sub_rsrc->unaligned_rect.left), + (dst_sub_rsrc->unaligned_rect.bottom - dst_sub_rsrc->unaligned_rect.top), dst_sub_rsrc->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_sub_rsrc->unaligned_rect.left & (src_desc->block_width - 1)) + && !(src_sub_rsrc->unaligned_rect.top & (src_desc->block_height - 1)) + && !(dst_sub_rsrc->unaligned_rect.left & (dst_desc->block_width - 1)) + && !(dst_sub_rsrc->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_sub_rsrc->data, src_sub_rsrc->row_pitch, src_sub_rsrc->slice_pitch, (void *)dst_sub_rsrc->data, + dst_sub_rsrc->row_pitch, dst_sub_rsrc->slice_pitch, &src_size, src_desc); return S_OK; }
@@ -2058,13 +2113,18 @@ 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_sub_rsrc->data, src_sub_rsrc->row_pitch, &src_sub_rsrc->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, - filter_flags, color_key); + struct d3dx_sub_resource uncompressed_sub_rsrc; + + set_d3dx_sub_resource_from_memory((const void *)uncompressed_mem, uncompressed_row_pitch, 0, NULL, + uncompressed_desc->format, 0, 0, src_sub_rsrc->width, src_sub_rsrc->height, 0, src_sub_rsrc->depth, + &uncompressed_sub_rsrc); + + hr = d3dx_load_sub_resource_from_sub_resource(dst_sub_rsrc, dst_desc, &uncompressed_sub_rsrc, + uncompressed_desc, filter_flags, color_key); } free(uncompressed_mem); return hr; @@ -2074,21 +2134,24 @@ static HRESULT d3dx_load_image_from_memory(void *dst_memory, uint32_t dst_row_pi if (dst_desc->type == FORMAT_DXT) { const struct pixel_format_desc *uncompressed_desc; + struct d3dx_sub_resource uncompressed_sub_rsrc; + 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_sub_rsrc->width, dst_sub_rsrc->height); + hr = d3dx_image_decompress(dst_sub_rsrc->data, dst_sub_rsrc->row_pitch, &aligned_rect, + &dst_sub_rsrc->unaligned_rect, &dst_size_aligned, dst_desc, &uncompressed_mem, &uncompressed_row_pitch, + &uncompressed_rect, &uncompressed_desc); if (FAILED(hr)) return hr;
- 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); + set_d3dx_sub_resource_from_memory((const void *)uncompressed_mem, uncompressed_row_pitch, 0, NULL, + uncompressed_desc->format, dst_sub_rsrc->unaligned_rect.left, dst_sub_rsrc->unaligned_rect.top, + dst_sub_rsrc->unaligned_rect.right, dst_sub_rsrc->unaligned_rect.bottom, 0, 1, &uncompressed_sub_rsrc); + + hr = d3dx_load_sub_resource_from_sub_resource(&uncompressed_sub_rsrc, uncompressed_desc, src_sub_rsrc, + src_desc, filter_flags, color_key); if (SUCCEEDED(hr)) { GLenum gl_format = 0; @@ -2111,7 +2174,7 @@ 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_sub_rsrc->data, dst_sub_rsrc->row_pitch); } free(uncompressed_mem); return hr; @@ -2119,8 +2182,9 @@ static HRESULT d3dx_load_image_from_memory(void *dst_memory, uint32_t dst_row_pi
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_sub_rsrc->data, src_sub_rsrc->row_pitch, src_sub_rsrc->slice_pitch, &src_size, src_desc, + (BYTE *)dst_sub_rsrc->data, dst_sub_rsrc->row_pitch, dst_sub_rsrc->slice_pitch, &dst_size, dst_desc, + color_key, src_sub_rsrc->palette); } else /* if ((filter & 0xf) == D3DX_FILTER_POINT) */ { @@ -2129,8 +2193,9 @@ 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_sub_rsrc->data, src_sub_rsrc->row_pitch, src_sub_rsrc->slice_pitch, &src_size, + src_desc, (BYTE *)dst_sub_rsrc->data, dst_sub_rsrc->row_pitch, dst_sub_rsrc->slice_pitch, &dst_size, + dst_desc, color_key, src_sub_rsrc->palette); }
return hr; @@ -2173,8 +2238,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_sub_resource src_sub_rsrc, dst_sub_rsrc; + RECT dst_rect_temp, dst_rect_aligned; IDirect3DSurface9 *surface; D3DSURFACE_DESC surfdesc; D3DLOCKED_RECT lockrect; @@ -2246,15 +2312,29 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, if (filter == D3DX_DEFAULT) filter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
+ hr = set_d3dx_sub_resource_from_memory(src_memory, src_pitch, 0, src_palette, srcformatdesc->format, + src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1, &src_sub_rsrc); + if (FAILED(hr)) + { + WARN("set_d3dx_sub_resource_from_memory failed with hr %#lx.\n", 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); + dst_sub_rsrc.data = lockrect.pBits; + dst_sub_rsrc.row_pitch = lockrect.Pitch; + dst_sub_rsrc.slice_pitch = 0; + dst_sub_rsrc.palette = dst_palette; + dst_sub_rsrc.width = dst_rect_aligned.right - dst_rect_aligned.left; + dst_sub_rsrc.height = dst_rect_aligned.bottom - dst_rect_aligned.top; + dst_sub_rsrc.depth = 1; + dst_sub_rsrc.unaligned_rect = *dst_rect; + OffsetRect(&dst_sub_rsrc.unaligned_rect, -dst_rect_aligned.left, -dst_rect_aligned.top); + + hr = d3dx_load_sub_resource_from_sub_resource(&dst_sub_rsrc, destformatdesc, &src_sub_rsrc, srcformatdesc, filter, + color_key); if (FAILED(hr)) WARN("d3dx_load_image_from_memory failed with hr %#lx\n", hr);
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 e2106f4b110..ea4a900c82b 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1933,9 +1933,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_sub_resource_decompress(struct d3dx_sub_resource *sub_rsrc, 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; @@ -1963,34 +1962,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(sub_rsrc->width * sub_rsrc->height * sub_rsrc->depth * uncompressed_desc->bytes_per_pixel))) return E_OUTOFMEMORY;
- if (unaligned_rect && EqualRect(rect, unaligned_rect)) - goto exit; + /* + * For compressed destination sub resources, 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, sub_rsrc->width, sub_rsrc->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, &sub_rsrc->unaligned_rect)) + goto exit; + } + + TRACE("Decompressing sub resource.\n"); + tmp_pitch = sub_rsrc->row_pitch * desc->block_width / desc->block_byte_count; + for (y = 0; y < sub_rsrc->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 * sub_rsrc->width * uncompressed_desc->bytes_per_pixel]; + for (x = 0; x < sub_rsrc->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 *)sub_rsrc->data, x + sub_rsrc->unaligned_rect.left, + y + sub_rsrc->unaligned_rect.top, ptr); + else if (!PtInRect(&sub_rsrc->unaligned_rect, pt)) + fetch_dxt_texel(tmp_pitch, (BYTE *)sub_rsrc->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 = sub_rsrc->width * uncompressed_desc->bytes_per_pixel; *out_desc = uncompressed_desc;
return S_OK; @@ -2111,10 +2124,9 @@ static HRESULT d3dx_load_sub_resource_from_sub_resource(struct d3dx_sub_resource const struct pixel_format_desc *uncompressed_desc; uint32_t uncompressed_row_pitch; void *uncompressed_mem = NULL; - RECT uncompressed_rect;
- hr = d3dx_image_decompress(src_sub_rsrc->data, src_sub_rsrc->row_pitch, &src_sub_rsrc->unaligned_rect, NULL, - &src_size, src_desc, &uncompressed_mem, &uncompressed_row_pitch, &uncompressed_rect, &uncompressed_desc); + hr = d3dx_sub_resource_decompress(src_sub_rsrc, src_desc, FALSE, &uncompressed_mem, &uncompressed_row_pitch, + &uncompressed_desc); if (SUCCEEDED(hr)) { struct d3dx_sub_resource uncompressed_sub_rsrc; @@ -2135,14 +2147,11 @@ static HRESULT d3dx_load_sub_resource_from_sub_resource(struct d3dx_sub_resource { const struct pixel_format_desc *uncompressed_desc; struct d3dx_sub_resource uncompressed_sub_rsrc; - RECT uncompressed_rect, aligned_rect; uint32_t uncompressed_row_pitch; void *uncompressed_mem = NULL;
- SetRect(&aligned_rect, 0, 0, dst_sub_rsrc->width, dst_sub_rsrc->height); - hr = d3dx_image_decompress(dst_sub_rsrc->data, dst_sub_rsrc->row_pitch, &aligned_rect, - &dst_sub_rsrc->unaligned_rect, &dst_size_aligned, dst_desc, &uncompressed_mem, &uncompressed_row_pitch, - &uncompressed_rect, &uncompressed_desc); + hr = d3dx_sub_resource_decompress(dst_sub_rsrc, dst_desc, TRUE, &uncompressed_mem, &uncompressed_row_pitch, + &uncompressed_desc); if (FAILED(hr)) return hr;
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 | 107 ++++++++++++++---------- dlls/d3dx9_36/tests/volume.c | 2 +- dlls/d3dx9_36/volume.c | 149 +++++++++++++--------------------- 4 files changed, 130 insertions(+), 136 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 4fc755338df..a442e6ea1b5 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -181,6 +181,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 set_d3dx_sub_resource_from_memory(const void *data, uint32_t row_pitch, uint32_t slice_pitch, + const PALETTEENTRY *palette, D3DFORMAT format, int32_t left, int32_t top, int32_t right, int32_t bottom, + uint32_t front, uint32_t back, struct d3dx_sub_resource *sub_rsrc); +HRESULT d3dx_load_sub_resource_from_sub_resource(struct d3dx_sub_resource *dst_sub_rsrc, + const struct pixel_format_desc *dst_desc, struct d3dx_sub_resource *src_sub_rsrc, + const struct pixel_format_desc *src_desc, uint32_t filter_flags, uint32_t color_key); +void get_aligned_rect(int32_t left, int32_t top, int32_t right, int32_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 ea4a900c82b..377467dce55 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -1934,11 +1934,12 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic }
static HRESULT d3dx_sub_resource_decompress(struct d3dx_sub_resource *sub_rsrc, 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) @@ -1962,7 +1963,9 @@ static HRESULT d3dx_sub_resource_decompress(struct d3dx_sub_resource *sub_rsrc, return E_NOTIMPL; }
- if (!(uncompressed_mem = malloc(sub_rsrc->width * sub_rsrc->height * sub_rsrc->depth * uncompressed_desc->bytes_per_pixel))) + uncompressed_row_pitch = sub_rsrc->width * uncompressed_desc->bytes_per_pixel; + uncompressed_slice_pitch = uncompressed_row_pitch * sub_rsrc->height; + if (!(uncompressed_mem = malloc(sub_rsrc->depth * uncompressed_slice_pitch))) return E_OUTOFMEMORY;
/* @@ -1985,25 +1988,31 @@ static HRESULT d3dx_sub_resource_decompress(struct d3dx_sub_resource *sub_rsrc,
TRACE("Decompressing sub resource.\n"); tmp_pitch = sub_rsrc->row_pitch * desc->block_width / desc->block_byte_count; - for (y = 0; y < sub_rsrc->height; ++y) + for (z = 0; z < sub_rsrc->depth; ++z) { - BYTE *ptr = &uncompressed_mem[y * sub_rsrc->width * uncompressed_desc->bytes_per_pixel]; - for (x = 0; x < sub_rsrc->width; ++x) + const BYTE *slice_data = ((BYTE *)sub_rsrc->data) + (sub_rsrc->slice_pitch * z); + + for (y = 0; y < sub_rsrc->height; ++y) { - const POINT pt = { x, y }; - - if (!is_dst) - fetch_dxt_texel(tmp_pitch, (BYTE *)sub_rsrc->data, x + sub_rsrc->unaligned_rect.left, - y + sub_rsrc->unaligned_rect.top, ptr); - else if (!PtInRect(&sub_rsrc->unaligned_rect, pt)) - fetch_dxt_texel(tmp_pitch, (BYTE *)sub_rsrc->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 < sub_rsrc->width; ++x) + { + const POINT pt = { x, y }; + + if (!is_dst) + fetch_dxt_texel(tmp_pitch, slice_data, x + sub_rsrc->unaligned_rect.left, + y + sub_rsrc->unaligned_rect.top, ptr); + else if (!PtInRect(&sub_rsrc->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 = sub_rsrc->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; @@ -2013,7 +2022,7 @@ exit: * Pack a d3dx_sub_resource structure for an image in memory, offsetting the * base address if necessary. */ -static HRESULT set_d3dx_sub_resource_from_memory(const void *data, uint32_t row_pitch, uint32_t slice_pitch, +HRESULT set_d3dx_sub_resource_from_memory(const void *data, uint32_t row_pitch, uint32_t slice_pitch, const PALETTEENTRY *palette, D3DFORMAT format, int32_t left, int32_t top, int32_t right, int32_t bottom, uint32_t front, uint32_t back, struct d3dx_sub_resource *sub_rsrc) { @@ -2067,7 +2076,7 @@ static const char *debug_d3dx_sub_resource(struct d3dx_sub_resource *sub_rsrc) sub_rsrc->width, sub_rsrc->height, sub_rsrc->depth, wine_dbgstr_rect(&sub_rsrc->unaligned_rect)); }
-static HRESULT d3dx_load_sub_resource_from_sub_resource(struct d3dx_sub_resource *dst_sub_rsrc, +HRESULT d3dx_load_sub_resource_from_sub_resource(struct d3dx_sub_resource *dst_sub_rsrc, const struct pixel_format_desc *dst_desc, struct d3dx_sub_resource *src_sub_rsrc, const struct pixel_format_desc *src_desc, uint32_t filter_flags, uint32_t color_key) { @@ -2095,6 +2104,7 @@ static HRESULT d3dx_load_sub_resource_from_sub_resource(struct d3dx_sub_resource 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_sub_rsrc->unaligned_rect.left & (src_desc->block_width - 1)) && !(src_sub_rsrc->unaligned_rect.top & (src_desc->block_height - 1)) @@ -2121,19 +2131,19 @@ static HRESULT d3dx_load_sub_resource_from_sub_resource(struct d3dx_sub_resource */ 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_sub_resource_decompress(src_sub_rsrc, src_desc, FALSE, &uncompressed_mem, &uncompressed_row_pitch, - &uncompressed_desc); + &uncompressed_slice_pitch, &uncompressed_desc); if (SUCCEEDED(hr)) { struct d3dx_sub_resource uncompressed_sub_rsrc;
- set_d3dx_sub_resource_from_memory((const void *)uncompressed_mem, uncompressed_row_pitch, 0, NULL, - uncompressed_desc->format, 0, 0, src_sub_rsrc->width, src_sub_rsrc->height, 0, src_sub_rsrc->depth, - &uncompressed_sub_rsrc); + set_d3dx_sub_resource_from_memory((const void *)uncompressed_mem, uncompressed_row_pitch, + uncompressed_slice_pitch, NULL, uncompressed_desc->format, 0, 0, src_sub_rsrc->width, + src_sub_rsrc->height, 0, src_sub_rsrc->depth, &uncompressed_sub_rsrc);
hr = d3dx_load_sub_resource_from_sub_resource(dst_sub_rsrc, dst_desc, &uncompressed_sub_rsrc, uncompressed_desc, filter_flags, color_key); @@ -2145,25 +2155,27 @@ static HRESULT d3dx_load_sub_resource_from_sub_resource(struct d3dx_sub_resource /* 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_sub_resource uncompressed_sub_rsrc; - uint32_t uncompressed_row_pitch; void *uncompressed_mem = NULL;
hr = d3dx_sub_resource_decompress(dst_sub_rsrc, dst_desc, TRUE, &uncompressed_mem, &uncompressed_row_pitch, - &uncompressed_desc); + &uncompressed_slice_pitch, &uncompressed_desc); if (FAILED(hr)) return hr;
- set_d3dx_sub_resource_from_memory((const void *)uncompressed_mem, uncompressed_row_pitch, 0, NULL, - uncompressed_desc->format, dst_sub_rsrc->unaligned_rect.left, dst_sub_rsrc->unaligned_rect.top, - dst_sub_rsrc->unaligned_rect.right, dst_sub_rsrc->unaligned_rect.bottom, 0, 1, &uncompressed_sub_rsrc); + set_d3dx_sub_resource_from_memory((const void *)uncompressed_mem, uncompressed_row_pitch, + uncompressed_slice_pitch, NULL, uncompressed_desc->format, dst_sub_rsrc->unaligned_rect.left, + dst_sub_rsrc->unaligned_rect.top, dst_sub_rsrc->unaligned_rect.right, + dst_sub_rsrc->unaligned_rect.bottom, 0, dst_sub_rsrc->depth, &uncompressed_sub_rsrc);
hr = d3dx_load_sub_resource_from_sub_resource(&uncompressed_sub_rsrc, uncompressed_desc, src_sub_rsrc, 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) @@ -2182,8 +2194,15 @@ static HRESULT d3dx_load_sub_resource_from_sub_resource(struct d3dx_sub_resource 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_sub_rsrc->data, dst_sub_rsrc->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_sub_rsrc->data) + (i * dst_sub_rsrc->slice_pitch); + + tx_compress_dxtn(4, dst_size_aligned.width, dst_size_aligned.height, uncompressed_mem_slice, gl_format, + dst_memory_slice, dst_sub_rsrc->row_pitch); + } } free(uncompressed_mem); return hr; @@ -2210,6 +2229,22 @@ static HRESULT d3dx_load_sub_resource_from_sub_resource(struct d3dx_sub_resource return hr; }
+void get_aligned_rect(int32_t left, int32_t top, int32_t right, int32_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 * @@ -2306,18 +2341,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;
@@ -2329,6 +2352,8 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface, 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..eedde9e6ab2 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_sub_resource src_sub_rsrc, dst_sub_rsrc; + 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,40 @@ 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 = set_d3dx_sub_resource_from_memory(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_sub_rsrc); + 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_sub_rsrc.data = locked_box.pBits; + dst_sub_rsrc.row_pitch = locked_box.RowPitch; + dst_sub_rsrc.slice_pitch = locked_box.SlicePitch; + dst_sub_rsrc.palette = dst_palette; + dst_sub_rsrc.width = dst_box_aligned.Right - dst_box_aligned.Left; + dst_sub_rsrc.height = dst_box_aligned.Bottom - dst_box_aligned.Top; + dst_sub_rsrc.depth = dst_box_aligned.Back - dst_box_aligned.Front; + SetRect(&dst_sub_rsrc.unaligned_rect, dst_box->Left, dst_box->Top, dst_box->Right, dst_box->Bottom); + OffsetRect(&dst_sub_rsrc.unaligned_rect, -dst_rect_aligned.left, -dst_rect_aligned.top); + + hr = d3dx_load_sub_resource_from_sub_resource(&dst_sub_rsrc, dst_format_desc, &src_sub_rsrc, src_format_desc, filter, + color_key); + if (FAILED(hr)) + WARN("d3dx_load_sub_resource_from_sub_resource failed with hr %#lx\n", hr); + + IDirect3DVolume9_UnlockBox(dst_volume); + return hr; }
HRESULT WINAPI D3DXLoadVolumeFromFileInMemory(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *dst_palette,
This seems to be unused at this point.
Maybe it's just me, but when I see an "offset" variable I kind of automatically read it as an integer. Maybe "subres_data", "subres_ptr", or just "ptr"?
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/surface.c:
return S_OK;
}
+/*
- Pack a d3dx_sub_resource structure for an image in memory, offsetting the
- base address if necessary.
- */
+static HRESULT set_d3dx_sub_resource_from_memory(const void *data, uint32_t row_pitch, uint32_t slice_pitch,
const PALETTEENTRY *palette, D3DFORMAT format, int32_t left, int32_t top, int32_t right, int32_t bottom,
uint32_t front, uint32_t back, struct d3dx_sub_resource *sub_rsrc)
It might be nicer to group those [in] params a bit, e.g. with a `D3DBOX`-like struct for the 6 "sides" values (btw, why this int/uint mix?)
The other thing that's a bit jarring here is the name of the function vs the API. This seems to be basically (part of) an object constructor, so we probably want to reflect that in the name, like `d3dx_sub_resource_init()` (while `_create()` would be the function doing the allocation + calling `_init()`). Looking at the whole branch, I think that's basically what you do for all those, so I think this might be only a matter of naming.
`d3dx_load_image_from_memory` is no more since this patch. I'd generally avoid referring to internal function names in error messages, they aren't particularly interesting or explanatory.
In this particular case, maybe we can do without the message entirely, assuming the called function already prints something in all the interesting failure cases.
Nitpick, we usually put the body of the `if` on its own line.
I think you can get rid of the `d3dx_resource_` prefix from the callback names.
Also, is the `__stdcall` necessary?
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/d3dx9_private.h:
- void (__stdcall *d3dx_resource_release)(struct d3dx_resource *resource);
+};
+#define d3dx_resource_release(resource) (resource)->resource_ops->d3dx_resource_release(resource) +struct d3dx_resource +{
- const struct d3dx_resource_ops *resource_ops;
- enum d3dx_resource_type d3dx_resource_type;
- D3DRESOURCETYPE resource_type;
- D3DFORMAT format;
- uint32_t width;
- uint32_t height;
- uint32_t depth;
- uint32_t mip_levels;
+};
Is `d3dx_resource_type` useful? If I'm reading this correctly, it's only ever used for the `assert()` in `d3dx_image_resource_from_resource`, which doesn't seem critical, especially considering how these d3dx_resource objects are going to be used (i.e. it seems unlikely that there's going to be a real chance to mix up d3dx_resource pointers with something else).
Then, as a first (probably won't be the last...) naming consideration: It seems more natural to call this e.g. `d3dx_texture`. What do you think? I realize that making the change would require touching a ton of places over many patches, so feel free to ignore this kind of comments, unless you end up having to rewrite stuff anyway. Which brings me to...
Would it be possible to implement all this in a reasonable fashion without callbacks? I haven't thought this all the way through so the answer might just be "no". That said, the idea would be to rework the code flow and move all the "context specific" calls out of generic code into the version / API-specific d3dx* side, which knows e.g. what particular `release()` function to call, thus avoiding extra indirection.
To me, it looks like this should be fine for the `release()` callback at least. The only 2 calls to `d3dx_resource_release()` in the d3dx_helpers.c from your branch are in error paths and can be presumably hoisted to the callers and replaced with direct calls. That's not immediately clear for the two other callbacks (`d3dx_resource_get_sub_resource` and `d3dx_resource_release_sub_resource`, introduced later). I think I'd still prefer to duplicate the per-layer, per-level loops, or to allocate extra temporary storage, if it means getting rid of callbacks. I can be convinced otherwise though.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/d3dx9_private.h:
D3DX_RESOURCE_TYPE_IMAGE = 1,
};
+struct d3dx_sub_resource
Another naming comment... I'm not crazy about the `d3dx_sub_resource` name: it feels a bit awkward when it's used "standalone", not immediately as part of a `d3dx_resource` (I think you setup a throw-away d3dx_sub_resource in a later patch).
I don't have great suggestions for this one. Maybe `d3dx_image` or `d3dx_surface`, but neither sounds super appealing to me.
Another option would be to enforce every `d3dx_sub_resource` to be tied to a `d3dx_resource`. It doesn't seem to be a better plan at a glance but I haven't given it much thought at this point.
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.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/volume.c:
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;
+}
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.
I left a bunch of comments of varying degrees of "seriousness". I'm particularly interested in the feasibility of the no callbacks thing, as that might simplify the code and has a cascade effect on a number of other bits. But don't feel like you have to make it work at all costs, no point in spending an inordinate amount of time to investigate that :sweat_smile: