[PATCH] d3dx9: Implement D3DXLoadSurfaceFromMemory for D3DX_FILTER_NONE and most ARGB and ABGR formats
Tony Wasserka
tony.wasserka at freenet.de
Sat Jul 18 04:03:26 CDT 2009
---
dlls/d3dx9_36/d3dx9_36_private.h | 18 +++++++
dlls/d3dx9_36/surface.c | 95 ++++++++++++++++++++++++++++++++++++-
dlls/d3dx9_36/tests/texture.c | 10 ++--
dlls/d3dx9_36/util.c | 51 ++++++++++++++++++++
4 files changed, 165 insertions(+), 9 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h
index 8568366..05d491f 100644
--- a/dlls/d3dx9_36/d3dx9_36_private.h
+++ b/dlls/d3dx9_36/d3dx9_36_private.h
@@ -31,9 +31,27 @@
#include "d3dx9.h"
/* for internal use */
+typedef enum _StaticFormatType {
+ FORMAT_ARGB,
+ FORMAT_ABGR,
+ FORMAT_UNKNOWN
+} StaticFormatType;
+
+typedef struct _StaticPixelFormatDesc {
+ D3DFORMAT format;
+ BYTE abits, rbits, gbits, bbits;
+ BYTE ashift, rshift, gshift, bshift;
+ DWORD amask, rmask, gmask, bmask;
+ UINT bytes_per_pixel;
+ StaticFormatType type;
+} StaticPixelFormatDesc;
+
HRESULT map_view_of_file(LPCWSTR filename, LPVOID *buffer, DWORD *length);
HRESULT load_resource_into_memory(HMODULE module, HRSRC resinfo, LPVOID *buffer, DWORD *length);
+void get_format_info(D3DFORMAT format, StaticPixelFormatDesc *desc);
+
+
extern const ID3DXBufferVtbl D3DXBuffer_Vtbl;
/* ID3DXBUFFER */
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c
index 0bee7c8..6a080b1 100644
--- a/dlls/d3dx9_36/surface.c
+++ b/dlls/d3dx9_36/surface.c
@@ -323,6 +323,62 @@ HRESULT WINAPI D3DXLoadSurfaceFromResourceW(LPDIRECT3DSURFACE9 pDestSurface,
return D3DXERR_INVALIDDATA;
}
+
+/************************************************************
+ * filter_copy_simple_data
+ *
+ * Copies the source buffer to the destination buffer, performing
+ * any necessary format conversion and color keying.
+ * Works only for ARGB and ABGR formats with 1 - 4 bytes per pixel.
+ */
+void filter_copy_simple_data(LPBYTE pSrc, UINT SrcPitch, POINT SrcSize, StaticPixelFormatDesc SrcFormat,
+ LPBYTE pDest, UINT DestPitch, POINT DestSize, StaticPixelFormatDesc DestFormat,
+ DWORD dwFilter)
+{
+ DWORD SrcShiftA, SrcShiftR, SrcShiftG, SrcShiftB;
+ DWORD DestShiftA, DestShiftR, DestShiftG, DestShiftB;
+ UINT MinWidth, MinHeight;
+ BYTE *pSrcPtr, *pDestPtr;
+ UINT x, y;
+
+ SrcShiftA = SrcFormat.ashift + max(SrcFormat.abits - DestFormat.abits, 0);
+ SrcShiftR = SrcFormat.rshift + max(SrcFormat.rbits - DestFormat.rbits, 0);
+ SrcShiftG = SrcFormat.gshift + max(SrcFormat.gbits - DestFormat.gbits, 0);
+ SrcShiftB = SrcFormat.bshift + max(SrcFormat.bbits - DestFormat.bbits, 0);
+ DestShiftA = DestFormat.ashift + max(DestFormat.abits - SrcFormat.abits, 0);
+ DestShiftR = DestFormat.rshift + max(DestFormat.rbits - SrcFormat.rbits, 0);
+ DestShiftG = DestFormat.gshift + max(DestFormat.gbits - SrcFormat.gbits, 0);
+ DestShiftB = DestFormat.bshift + max(DestFormat.bbits - SrcFormat.bbits, 0);
+
+ MinWidth = (SrcSize.x < DestSize.x) ? SrcSize.x : DestSize.x;
+ MinHeight = (SrcSize.y < DestSize.y) ? SrcSize.y : DestSize.y;
+
+ for(y = 0;y < MinHeight;y++) {
+ pSrcPtr = pSrc + y * SrcPitch;
+ pDestPtr = pDest + y * DestPitch;
+ for(x = 0;x < MinWidth;x++) {
+ DWORD Col = *(DWORD*)pSrcPtr;
+ DWORD *pPixel = (DWORD*)pDestPtr;
+
+ /* convert bits per channel */
+ if(SrcFormat.abits) *pPixel = ((Col >> SrcShiftA) << DestShiftA) & DestFormat.amask;
+ else *pPixel = DestFormat.amask;
+
+ if(SrcFormat.rbits) *pPixel += ((Col >> SrcShiftR) << DestShiftR) & DestFormat.rmask;
+ else *pPixel |= DestFormat.rmask;
+
+ if(SrcFormat.gbits) *pPixel += ((Col >> SrcShiftG) << DestShiftG) & DestFormat.gmask;
+ else *pPixel |= DestFormat.gmask;
+
+ if(SrcFormat.bbits) *pPixel += ((Col >> SrcShiftB) << DestShiftB) & DestFormat.bmask;
+ else *pPixel |= DestFormat.bmask;
+
+ pSrcPtr += SrcFormat.bytes_per_pixel;
+ pDestPtr += DestFormat.bytes_per_pixel;
+ }
+ }
+}
+
/************************************************************
* D3DXLoadSurfaceFromMemory
*
@@ -350,7 +406,8 @@ HRESULT WINAPI D3DXLoadSurfaceFromResourceW(LPDIRECT3DSURFACE9 pDestSurface,
* E_FAIL, if SrcFormat is D3DFMT_UNKNOWN or the dimensions of pSrcRect are invalid
*
* NOTES
- * pSrcRect specifies the dimensions of the source data
+ * pSrcRect specifies the dimensions of the source data;
+ * negative values for pSrcRect are allowed as we're only looking at the width and height anyways.
*
*/
HRESULT WINAPI D3DXLoadSurfaceFromMemory(LPDIRECT3DSURFACE9 pDestSurface,
@@ -364,11 +421,43 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(LPDIRECT3DSURFACE9 pDestSurface,
DWORD dwFilter,
D3DCOLOR Colorkey)
{
- TRACE("stub\n");
+ StaticPixelFormatDesc SrcFormatDesc, DestFormatDesc;
+ D3DSURFACE_DESC SurfDesc;
+ D3DLOCKED_RECT LockRect;
+ POINT SrcSize, DestSize;
+ HRESULT hr;
+ TRACE("(void)\n");
if( !pDestSurface || !pSrcMemory || !pSrcRect ) return D3DERR_INVALIDCALL;
if(SrcFormat == D3DFMT_UNKNOWN || pSrcRect->left >= pSrcRect->right || pSrcRect->top >= pSrcRect->bottom) return E_FAIL;
- return E_NOTIMPL;
+
+ IDirect3DSurface9_GetDesc(pDestSurface, &SurfDesc);
+ if(dwFilter != D3DX_FILTER_NONE) return E_NOTIMPL;
+
+ get_format_info(SrcFormat, &SrcFormatDesc);
+ get_format_info(SurfDesc.Format, &DestFormatDesc);
+ if( SrcFormatDesc.type == FORMAT_UNKNOWN || SrcFormatDesc.bytes_per_pixel > 4) return E_NOTIMPL;
+ if(DestFormatDesc.type == FORMAT_UNKNOWN || DestFormatDesc.bytes_per_pixel > 4) return E_NOTIMPL;
+
+ SrcSize.x = pSrcRect->right - pSrcRect->left;
+ SrcSize.y = pSrcRect->bottom - pSrcRect->top;
+ if( !pDestRect ) {
+ DestSize.x = SurfDesc.Width;
+ DestSize.y = SurfDesc.Height;
+ } else {
+ DestSize.x = pDestRect->right - pDestRect->left;
+ DestSize.y = pDestRect->bottom - pDestRect->top;
+ }
+
+ hr = IDirect3DSurface9_LockRect(pDestSurface, &LockRect, pDestRect, 0);
+ if(FAILED(hr)) return D3DXERR_INVALIDDATA;
+
+ filter_copy_simple_data((BYTE*)pSrcMemory, SrcPitch, SrcSize, SrcFormatDesc,
+ LockRect.pBits, LockRect.Pitch, DestSize, DestFormatDesc,
+ dwFilter);
+
+ IDirect3DSurface9_UnlockRect(pDestSurface);
+ return D3D_OK;
}
/************************************************************
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c
index 7f10e2d..2a717cb 100644
--- a/dlls/d3dx9_36/tests/texture.c
+++ b/dlls/d3dx9_36/tests/texture.c
@@ -303,13 +303,11 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
/* D3DXLoadSurfaceFromMemory */
SetRect(&rect, 0, 0, 2, 2);
- todo_wine {
- hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_DEFAULT, 0);
- ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_FILTER_NONE, 0);
+ ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
- hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata, D3DFMT_A8R8G8B8, 0, NULL, &rect, D3DX_DEFAULT, 0);
- ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
- }
+ hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata, D3DFMT_A8R8G8B8, 0, NULL, &rect, D3DX_FILTER_NONE, 0);
+ ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK);
hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, NULL, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_DEFAULT, 0);
ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
diff --git a/dlls/d3dx9_36/util.c b/dlls/d3dx9_36/util.c
index ff41ee7..8537738 100644
--- a/dlls/d3dx9_36/util.c
+++ b/dlls/d3dx9_36/util.c
@@ -20,6 +20,37 @@
#include "wine/debug.h"
#include "d3dx9_36_private.h"
+
+/************************************************************
+ * pixel format table providing info about number of bytes per pixel,
+ * number of bits per channel and format type.
+ *
+ * Call get_format_info to request information about a specific format.
+ */
+static const StaticPixelFormatDesc formats[] =
+{
+ /* format bits per channel shifts per channel masks per channel bpp type */
+ { D3DFMT_R8G8B8, 0, 8, 8, 8, 0, 16, 8, 0, 0x0, 0xFF0000, 0xFF00, 0xFF, 3, FORMAT_ARGB },
+ { D3DFMT_A8R8G8B8, 8, 8, 8, 8, 24, 16, 8, 0, 0xFF000000, 0xFF0000, 0xFF00, 0xFF, 4, FORMAT_ARGB },
+ { D3DFMT_X8R8G8B8, 0, 8, 8, 8, 0, 16, 8, 0, 0x0, 0xFF0000, 0xFF00, 0xFF, 4, FORMAT_ARGB },
+ { D3DFMT_A8B8G8R8, 8, 8, 8, 8, 24, 0, 8, 16, 0xFF000000, 0xFF, 0xFF00, 0xFF0000, 4, FORMAT_ABGR },
+ { D3DFMT_X8B8G8R8, 0, 8, 8, 8, 0, 0, 8, 16, 0x0, 0xFF, 0xFF00, 0xFF0000, 4, FORMAT_ABGR },
+ { D3DFMT_R5G6B5, 0, 5, 6, 5, 0, 11, 5, 0, 0x0, 0xF800, 0x7E0, 0x1F, 2, FORMAT_ARGB },
+ { D3DFMT_X1R5G5B5, 0, 5, 5, 5, 0, 10, 5, 0, 0x0, 0x7C00, 0x3E0, 0x1F, 2, FORMAT_ARGB },
+ { D3DFMT_A1R5G5B5, 1, 5, 5, 5, 15, 10, 5, 0, 0x8000, 0x7C00, 0x3E0, 0x1F, 2, FORMAT_ARGB },
+ { D3DFMT_R3G3B2, 0, 3, 3, 2, 0, 5, 2, 0, 0x0, 0xE0, 0x1C, 0x3, 1, FORMAT_ARGB },
+ { D3DFMT_A8R3G3B2, 8, 3, 3, 2, 8, 5, 2, 0, 0xFF00, 0xE0, 0x1C, 0x3, 2, FORMAT_ARGB },
+ { D3DFMT_A4R4G4B4, 4, 4, 4, 4, 12, 8, 4, 0, 0xF000, 0xF00, 0xF0, 0xF, 2, FORMAT_ARGB },
+ { D3DFMT_X4R4G4B4, 0, 4, 4, 4, 0, 8, 4, 0, 0x0, 0xF00, 0xF0, 0xF, 2, FORMAT_ARGB },
+ { D3DFMT_A2R10G10B10, 2, 10, 10, 10, 30, 20, 10, 0, 0xC0000000, 0x3FF00000, 0xFFC00, 0x3FF, 4, FORMAT_ARGB },
+ { D3DFMT_A2B10G10R10, 2, 10, 10, 10, 30, 0, 10, 20, 0xC0000000, 0x3FF, 0xFFC00, 0x3FF00000, 4, FORMAT_ABGR },
+ { D3DFMT_G16R16, 0, 16, 16, 0, 0, 0, 16, 0, 0x0, 0xFFFF, 0xFFFF0000, 0x0, 4, FORMAT_ABGR },
+ { D3DFMT_A8, 8, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0x0, 0x0, 0x0, 1, FORMAT_ARGB },
+
+ { D3DFMT_UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x0, 0x0, 0x0, 0, FORMAT_UNKNOWN }, /* marks last element */
+};
+
+
/************************************************************
* map_view_of_file
*
@@ -102,3 +133,23 @@ HRESULT load_resource_into_memory(HMODULE module, HRSRC resinfo, LPVOID *buffer,
return S_OK;
}
+
+
+/************************************************************
+ * get_format_info
+ *
+ * Returns information about the specified format.
+ * If the format is unsupported, it's filled with the D3DFMT_UNKNOWN desc.
+ *
+ * PARAMS
+ * format [I] format whose description is queried
+ * desc [O] pointer to a StaticPixelFormatDesc structure
+ *
+ */
+void get_format_info(D3DFORMAT format, StaticPixelFormatDesc *desc)
+{
+ int i = 0;
+ while(formats[i].format != format && formats[i].format != D3DFMT_UNKNOWN) i++;
+
+ memcpy(desc, &formats[i].format, sizeof(StaticPixelFormatDesc));
+}
--
1.6.3.2
--------------060401040805000509040508--
More information about the wine-patches
mailing list