[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