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,