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,