[PATCH] d3dx9: Implement surface copying for all ARGB 1 - 4 bpp formats
Tony Wasserka
tony.wasserka at freenet.de
Wed Jul 15 10:15:48 CDT 2009
---
dlls/d3dx9_36/surface.c | 112 +++++++++++++++++++++++++++++++++++++++--------
1 files changed, 94 insertions(+), 18 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c
index e0aad21..aec05a4 100644
--- a/dlls/d3dx9_36/surface.c
+++ b/dlls/d3dx9_36/surface.c
@@ -323,6 +323,90 @@ HRESULT WINAPI D3DXLoadSurfaceFromResourceW(LPDIRECT3DSURFACE9 pDestSurface,
return D3DXERR_INVALIDDATA;
}
+
+/************************************************************
+ * get_masks
+ *
+ * Returns the masks necessary to split a pixel into its components.
+ * Works only for ARGB formats with 1 - 4 bytes per pixel.
+ *
+ */
+void get_masks(StaticPixelFormatDesc format, DWORD *amask, DWORD *rmask, DWORD *gmask, DWORD *bmask)
+{
+ *amask = ((1 << format.abits) - 1) << (format.rbits + format.gbits + format.bbits);
+ *rmask = ((1 << format.rbits) - 1) << (format.gbits + format.bbits);
+ *gmask = ((1 << format.gbits) - 1) << (format.bbits);
+ *bmask = (1 << format.bbits) - 1;
+}
+
+/************************************************************
+ * get_shifts
+ *
+ * Returns the (nonnegative) shifts necessary to extract each component of a pixel
+ * and scale it to the destination format's bits per channel.
+ * Works only for ARGB formats.
+ *
+ */
+void get_shifts(StaticPixelFormatDesc srcformat, StaticPixelFormatDesc destformat, DWORD *ashift, DWORD *rshift, DWORD *gshift, DWORD *bshift)
+{
+ *ashift = srcformat.rbits + srcformat.gbits + srcformat.bbits + max(srcformat.abits - destformat.abits, 0);
+ *rshift = srcformat.gbits + srcformat.bbits + max(srcformat.rbits - destformat.rbits, 0);
+ *gshift = srcformat.bbits + max(srcformat.gbits - destformat.gbits, 0);
+ *bshift = max(srcformat.bbits - destformat.bbits, 0);
+}
+
+/************************************************************
+ * filter_copy_simple_data
+ *
+ * Copies the source buffer to the destination buffer, performing
+ * any necessary format conversion and color keying.
+ * Works only for ARGB 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;
+ DWORD MaskA, MaskR, MaskG, MaskB;
+ UINT MinWidth, MinHeight;
+ BYTE *pSrcPtr, *pDestPtr;
+ UINT x, y;
+
+ get_shifts( SrcFormat, DestFormat, &SrcShiftA, &SrcShiftR, &SrcShiftG, &SrcShiftB);
+ get_shifts(DestFormat, SrcFormat, &DestShiftA, &DestShiftR, &DestShiftG, &DestShiftB);
+
+ get_masks(DestFormat, &MaskA, &MaskR, &MaskG, &MaskB);
+
+ 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) & MaskA;
+ else *pPixel = MaskA;
+
+ if(SrcFormat.rbits) *pPixel += ((Col >> SrcShiftR) << DestShiftR) & MaskR;
+ else *pPixel |= MaskR;
+
+ if(SrcFormat.gbits) *pPixel += ((Col >> SrcShiftG) << DestShiftG) & MaskG;
+ else *pPixel |= MaskG;
+
+ if(SrcFormat.bbits) *pPixel += ((Col >> SrcShiftB) << DestShiftB) & MaskB;
+ else *pPixel |= MaskB;
+
+ pSrcPtr += SrcFormat.bpp;
+ pDestPtr += DestFormat.bpp;
+ }
+ }
+}
+
/************************************************************
* D3DXLoadSurfaceFromMemory
*
@@ -365,19 +449,23 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(LPDIRECT3DSURFACE9 pDestSurface,
DWORD dwFilter,
D3DCOLOR Colorkey)
{
+ StaticPixelFormatDesc SrcFormatDesc, DestFormatDesc;
D3DSURFACE_DESC SurfDesc;
D3DLOCKED_RECT LockRect;
POINT SrcSize, DestSize;
HRESULT hr;
- UINT x, y;
- DWORD *pSrcPtr, *pDestPtr;
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;
IDirect3DSurface9_GetDesc(pDestSurface, &SurfDesc);
- if(SrcFormat != D3DFMT_A8R8G8B8 || SurfDesc.Format != D3DFMT_A8R8G8B8 || dwFilter != D3DX_FILTER_NONE) return E_NOTIMPL;
+ if(dwFilter != D3DX_FILTER_NONE) return E_NOTIMPL;
+
+ get_format_info(SrcFormat, &SrcFormatDesc);
+ get_format_info(SurfDesc.Format, &DestFormatDesc);
+ if( SrcFormatDesc.type != FORMAT_ARGB || SrcFormatDesc.bpp > 4) return E_NOTIMPL;
+ if(DestFormatDesc.type != FORMAT_ARGB || DestFormatDesc.bpp > 4) return E_NOTIMPL;
SrcSize.x = pSrcRect->right - pSrcRect->left;
SrcSize.y = pSrcRect->bottom - pSrcRect->top;
@@ -392,21 +480,9 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(LPDIRECT3DSURFACE9 pDestSurface,
hr = IDirect3DSurface9_LockRect(pDestSurface, &LockRect, pDestRect, 0);
if(FAILED(hr)) return D3DXERR_INVALIDDATA;
- pSrcPtr = (DWORD*)pSrcMemory;
- pDestPtr = LockRect.pBits;
- for(y = 0;y < DestSize.y;y++) {
- if(y >= SrcSize.y) break;
-
- pSrcPtr = (DWORD*)((BYTE*)pSrcMemory + y * SrcPitch);
- pDestPtr = (DWORD*)((BYTE*)LockRect.pBits + y * LockRect.Pitch);
- for(x = 0;x < DestSize.x;x++) {
- if(x >= SrcSize.x) break;
-
- *pDestPtr = (*pSrcPtr != Colorkey) ? (*pSrcPtr) : 0;
- pDestPtr++;
- pSrcPtr++;
- }
- }
+ filter_copy_simple_data((BYTE*)pSrcMemory, SrcPitch, SrcSize, SrcFormatDesc,
+ LockRect.pBits, LockRect.Pitch, DestSize, DestFormatDesc,
+ dwFilter);
IDirect3DSurface9_UnlockRect(pDestSurface);
return D3D_OK;
--
1.6.0.2
--------------010104070505080700020900--
More information about the wine-patches
mailing list