diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 199209f6c03..f82f1b1ba61 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -304,11 +304,128 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(LPDIRECT3DSURFACE9 pDestSurface, D3DCOLOR Colorkey, D3DXIMAGE_INFO *pSrcInfo) { - FIXME("(%p, %p, %p, %p, %d, %p, %d, %x, %p): stub\n", pDestSurface, pDestPalette, - pDestRect, pSrcData, SrcDataSize, pSrcRect, dwFilter, Colorkey, pSrcInfo); + D3DXIMAGE_INFO imginfo; + HRESULT hr; - if( !pDestSurface || !pSrcData | !SrcDataSize ) return D3DERR_INVALIDCALL; - return E_NOTIMPL; + TRACE("(%p, %p, %p, %p, %d, %p, %d, %x, %p)\n", pDestSurface, pDestPalette, pDestRect, pSrcData, + SrcDataSize, pSrcRect, dwFilter, Colorkey, pSrcInfo); + + if (!pDestSurface || !pSrcData | !SrcDataSize) + return D3DERR_INVALIDCALL; + + hr = D3DXGetImageInfoFromFileInMemory(pSrcData, SrcDataSize, &imginfo); + + if (FAILED(hr)) + return hr; + + switch (imginfo.ImageFileFormat) + { + case D3DXIFF_BMP: + case D3DXIFF_PNG: + case D3DXIFF_JPG: + { + IWICImagingFactory *factory; + IWICBitmapDecoder *decoder; + IWICBitmapFrameDecode *bitmapframe; + IWICStream *stream; + + const PixelFormatDesc *formatdesc; + WICRect wicrect; + RECT rect; + + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + if (FAILED(CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, &IID_IWICImagingFactory, (void**)&factory))) + goto cleanup_err; + + if (FAILED(IWICImagingFactory_CreateStream(factory, &stream))) + { + IWICImagingFactory_Release(factory); + goto cleanup_err; + } + + IWICStream_InitializeFromMemory(stream, (BYTE*)pSrcData, SrcDataSize); + + hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream*)stream, NULL, 0, &decoder); + + IStream_Release(stream); + IWICImagingFactory_Release(factory); + + if (FAILED(hr)) + goto cleanup_err; + + hr = IWICBitmapDecoder_GetFrame(decoder, 0, &bitmapframe); + + if (FAILED(hr)) + goto cleanup_bmp; + + if (pSrcRect) + { + wicrect.X = pSrcRect->left; + wicrect.Y = pSrcRect->top; + wicrect.Width = pSrcRect->right - pSrcRect->left; + wicrect.Height = pSrcRect->bottom - pSrcRect->top; + } + else + { + wicrect.X = 0; + wicrect.Y = 0; + wicrect.Width = imginfo.Width; + wicrect.Height = imginfo.Height; + } + + SetRect(&rect, 0, 0, wicrect.Width, wicrect.Height); + + formatdesc = get_format_info(imginfo.Format); + + if (formatdesc->format == D3DFMT_UNKNOWN) + { + FIXME("Unsupported pixel format\n"); + hr = D3DXERR_INVALIDDATA; + } + else + { + BYTE *buffer; + DWORD pitch; + + pitch = formatdesc->bytes_per_pixel * wicrect.Width; + buffer = HeapAlloc(GetProcessHeap(), 0, pitch * wicrect.Height); + + hr = IWICBitmapFrameDecode_CopyPixels(bitmapframe, &wicrect, pitch, + pitch * wicrect.Height, buffer); + + if (SUCCEEDED(hr)) + { + hr = D3DXLoadSurfaceFromMemory(pDestSurface, pDestPalette, pDestRect, + buffer, imginfo.Format, pitch, + NULL, &rect, dwFilter, Colorkey); + } + + HeapFree(GetProcessHeap(), 0, buffer); + } + +cleanup_bmp: + IWICBitmapFrameDecode_Release(bitmapframe); + IWICBitmapDecoder_Release(decoder); + +cleanup_err: + CoUninitialize(); + + if (FAILED(hr)) + return D3DXERR_INVALIDDATA; + + break; + } + + default: + FIXME("Unsupported image file format\n"); + return E_NOTIMPL; + } + + if (pSrcInfo) + *pSrcInfo = imginfo; + + return D3D_OK; } /************************************************************ diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index a996e6d6f4b..ab47c6f73f4 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -252,10 +252,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) } else skip("Couldn't create \"testbitmap.bmp\"\n"); if(testdummy_ok) { - todo_wine { - hr = D3DXLoadSurfaceFromFileA(surf, NULL, NULL, "testdummy.bmp", NULL, D3DX_DEFAULT, 0, NULL); - ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromFile returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); - } + hr = D3DXLoadSurfaceFromFileA(surf, NULL, NULL, "testdummy.bmp", NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromFile returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); } else skip("Couldn't create \"testdummy.bmp\"\n"); hr = D3DXLoadSurfaceFromFileA(surf, NULL, NULL, NULL, NULL, D3DX_DEFAULT, 0, NULL); @@ -269,11 +267,11 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) todo_wine { hr = D3DXLoadSurfaceFromResourceA(surf, NULL, NULL, NULL, MAKEINTRESOURCE(IDB_BITMAP_1x1), NULL, D3DX_DEFAULT, 0, NULL); ok(hr == D3D_OK, "D3DXLoadSurfaceFromResource returned %#x, expected %#x\n", hr, D3D_OK); - - hr = D3DXLoadSurfaceFromResourceA(surf, NULL, NULL, NULL, MAKEINTRESOURCE(IDD_BITMAPDATA_1x1), NULL, D3DX_DEFAULT, 0, NULL); - ok(hr == D3D_OK, "D3DXLoadSurfaceFromResource returned %#x, expected %#x\n", hr, D3D_OK); } + hr = D3DXLoadSurfaceFromResourceA(surf, NULL, NULL, NULL, MAKEINTRESOURCE(IDD_BITMAPDATA_1x1), NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromResource returned %#x, expected %#x\n", hr, D3D_OK); + hr = D3DXLoadSurfaceFromResourceA(surf, NULL, NULL, NULL, NULL, NULL, D3DX_DEFAULT, 0, NULL); ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); @@ -288,11 +286,11 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device) todo_wine { hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, bmp01, sizeof(bmp01), NULL, D3DX_DEFAULT, 0, NULL); ok(hr == D3D_OK, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); - - hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, noimage, sizeof(noimage), NULL, D3DX_DEFAULT, 0, NULL); - ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); } + hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, noimage, sizeof(noimage), NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, bmp01, 0, NULL, D3DX_DEFAULT, 0, NULL); ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);