[PATCH] d3dx9: Implement point filtering of ARGB surface data in D3DXLoadSurfaceFromMemory

Tony Wasserka tony.wasserka at freenet.de
Sun Jan 31 05:52:58 CST 2010


---
 dlls/d3dx9_36/surface.c       |  119 ++++++++++++++++++++++++++++------------
 dlls/d3dx9_36/tests/texture.c |    6 +--
 2 files changed, 85 insertions(+), 40 deletions(-)

diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c
index 4d8d1f6..59b1d9c 100644
--- a/dlls/d3dx9_36/surface.c
+++ b/dlls/d3dx9_36/surface.c
@@ -325,15 +325,17 @@ HRESULT WINAPI D3DXLoadSurfaceFromResourceW(LPDIRECT3DSURFACE9 pDestSurface,
 
 
 /************************************************************
- * copy_simple_data
+ * point_filter_simple_data
  *
  * Copies the source buffer to the destination buffer, performing
- * any necessary format conversion and color keying.
+ * any necessary format conversion and color keying. If
+ * D3DX_FILTER_POINT is specified and srcsize doesn't match destsize,
+ * a simple point filter is applied as well.
  * Works only for ARGB formats with 1 - 4 bytes per pixel.
  */
-static void copy_simple_data(CONST BYTE *src,  UINT  srcpitch, POINT  srcsize, CONST PixelFormatDesc  *srcformat,
-                             CONST BYTE *dest, UINT destpitch, POINT destsize, CONST PixelFormatDesc *destformat,
-                             DWORD dwFilter)
+static void point_filter_simple_data(CONST BYTE *src,  UINT  srcpitch, POINT  srcsize, CONST PixelFormatDesc  *srcformat,
+                                     CONST BYTE *dest, UINT destpitch, POINT destsize, CONST PixelFormatDesc *destformat,
+                                     DWORD filter)
 {
     DWORD srcshift[4], destshift[4];
     DWORD srcmask[4], destmask[4];
@@ -342,7 +344,7 @@ static void copy_simple_data(CONST BYTE *src,  UINT  srcpitch, POINT  srcsize, C
     DWORD channelmask = 0;
 
     UINT minwidth, minheight;
-    BYTE *srcptr, *destptr;
+    BYTE *srcptr, *destptr, *bufptr;
     UINT i, x, y;
 
     ZeroMemory(channels, sizeof(channels));
@@ -368,35 +370,72 @@ static void copy_simple_data(CONST BYTE *src,  UINT  srcpitch, POINT  srcsize, C
     minwidth  = (srcsize.x < destsize.x) ? srcsize.x : destsize.x;
     minheight = (srcsize.y < destsize.y) ? srcsize.y : destsize.y;
 
-    for(y = 0;y < minheight;y++) {
-        srcptr  = (BYTE*)( src + y *  srcpitch);
-        destptr = (BYTE*)(dest + y * destpitch);
-        for(x = 0;x < minwidth;x++) {
-            /* extract source color components */
-            if(srcformat->type == FORMAT_ARGB) {
-                const DWORD col = *(DWORD*)srcptr;
-                for(i = 0;i < 4;i++)
-                    if(process_channel[i])
-                        channels[i] = (col & srcmask[i]) >> srcshift[i];
+    if((srcsize.x == destsize.x && srcsize.y == destsize.y) || (filter & 0xF)==D3DX_FILTER_NONE) {
+        for(y = 0;y < minheight;y++) {
+            srcptr  = (BYTE*)( src + y *  srcpitch);
+            destptr = (BYTE*)(dest + y * destpitch);
+            for(x = 0;x < minwidth;x++) {
+                /* extract source color components */
+                if(srcformat->type == FORMAT_ARGB) {
+                    const DWORD col = *(DWORD*)srcptr;
+                    for(i = 0;i < 4;i++)
+                        if(process_channel[i])
+                            channels[i] = (col & srcmask[i]) >> srcshift[i];
+                }
+
+                /* recombine the components */
+                if(destformat->type == FORMAT_ARGB) {
+                    DWORD* const pixel = (DWORD*)destptr;
+                    *pixel = 0;
+
+                    for(i = 0;i < 4;i++) {
+                        if(process_channel[i]) {
+                            /* necessary to make sure that e.g. an X4R4G4B4 white maps to an R8G8B8 white instead of 0xf0f0f0 */
+                            signed int shift;
+                            for(shift = destshift[i]; shift > destformat->shift[i]; shift -= srcformat->bits[i]) *pixel |= channels[i] << shift;
+                            *pixel |= (channels[i] >> (destformat->shift[i] - shift)) << destformat->shift[i];
+                        }
+                    }
+                    *pixel |= channelmask;   /* new channels are set to their maximal value */
+                }
+                srcptr  +=  srcformat->bytes_per_pixel;
+                destptr += destformat->bytes_per_pixel;
             }
+        }
+        /* TODO: black out remaining areas of dest surface */
+    } else /*if((filter & 0xF)==D3DX_FILTER_POINT)*/ {
+        for(y = 0;y < destsize.y;y++) {
+            destptr = (BYTE*)dest + y * destpitch;
+            srcptr = (BYTE*)src + srcpitch * (y * srcsize.y / destsize.y);
+            bufptr  = (BYTE*)src + srcpitch * (y * srcsize.y / destsize.y);
+
+            for(x = 0;x < destsize.x;x++) {
+                /* extract source color components */
+                if(srcformat->type == FORMAT_ARGB) {
+                    const DWORD col = *(DWORD*)srcptr;
+                    for(i = 0;i < 4;i++)
+                        if(process_channel[i])
+                            channels[i] = (col & srcmask[i]) >> srcshift[i];
+                }
 
-            /* recombine the components */
-            if(destformat->type == FORMAT_ARGB) {
-                DWORD* const pixel = (DWORD*)destptr;
-                *pixel = 0;
-
-                for(i = 0;i < 4;i++) {
-                    if(process_channel[i]) {
-                        /* necessary to make sure that e.g. an X4R4G4B4 white maps to an R8G8B8 white instead of 0xf0f0f0 */
-                        signed int shift;
-                        for(shift = destshift[i]; shift > destformat->shift[i]; shift -= srcformat->bits[i]) *pixel |= channels[i] << shift;
-                        *pixel |= (channels[i] >> (destformat->shift[i] - shift)) << destformat->shift[i];
+                /* recombine the components */
+                if(destformat->type == FORMAT_ARGB) {
+                    DWORD* const pixel = (DWORD*)destptr;
+                    *pixel = 0;
+
+                    for(i = 0;i < 4;i++) {
+                        if(process_channel[i]) {
+                            /* necessary to make sure that e.g. an X4R4G4B4 white maps to an R8G8B8 white instead of 0xf0f0f0 */
+                            signed int shift;
+                            for(shift = destshift[i]; shift > destformat->shift[i]; shift -= srcformat->bits[i]) *pixel |= channels[i] << shift;
+                            *pixel |= (channels[i] >> (destformat->shift[i] - shift)) << destformat->shift[i];
+                        }
                     }
+                    *pixel |= channelmask;   /* new channels are set to their maximal value */
                 }
-                *pixel |= channelmask;   /* new channels are set to their maximal value */
+                srcptr = bufptr + (x * srcsize.x / destsize.x) * srcformat->bytes_per_pixel;
+                destptr += destformat->bytes_per_pixel;
             }
-            srcptr  +=  srcformat->bytes_per_pixel;
-            destptr += destformat->bytes_per_pixel;
         }
     }
 }
@@ -423,13 +462,14 @@ static void copy_simple_data(CONST BYTE *src,  UINT  srcpitch, POINT  srcsize, C
  *   Success: D3D_OK, if we successfully load the pixel data into our surface or
  *                    if pSrcMemory is NULL but the other parameters are valid
  *   Failure: D3DERR_INVALIDCALL, if pDestSurface, SrcPitch or pSrcRect are NULL or
- *                                if SrcFormat is an invalid format (other than D3DFMT_UNKNOWN)
+ *                                if SrcFormat is an invalid format (other than D3DFMT_UNKNOWN) or
+ *                                if the dimensions specified by pDestRect exceed the dest surface's boundaries
  *            D3DXERR_INVALIDDATA, if we fail to lock pDestSurface
  *            E_FAIL, if SrcFormat is D3DFMT_UNKNOWN or the dimensions of pSrcRect are invalid
  *
  * NOTES
  *   pSrcRect specifies the dimensions of the source data;
- *   negative values for pSrcRect are allowed as we're only looking at the width and height anyway.
+ *   negative values for pSrcRect are allowed.
  *
  */
 HRESULT WINAPI D3DXLoadSurfaceFromMemory(LPDIRECT3DSURFACE9 pDestSurface,
@@ -453,7 +493,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(LPDIRECT3DSURFACE9 pDestSurface,
     if( !pDestSurface || !pSrcMemory || !pSrcRect ) return D3DERR_INVALIDCALL;
     if(SrcFormat == D3DFMT_UNKNOWN || pSrcRect->left >= pSrcRect->right || pSrcRect->top >= pSrcRect->bottom) return E_FAIL;
 
-    if(dwFilter != D3DX_FILTER_NONE) return E_NOTIMPL;
+    if(dwFilter == D3DX_DEFAULT) dwFilter = D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER;
 
     IDirect3DSurface9_GetDesc(pDestSurface, &surfdesc);
 
@@ -470,14 +510,21 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(LPDIRECT3DSURFACE9 pDestSurface,
     } else {
         destsize.x = pDestRect->right - pDestRect->left;
         destsize.y = pDestRect->bottom - pDestRect->top;
+        if(destsize.x > surfdesc.Width) return D3DERR_INVALIDCALL;
+        if(destsize.y > surfdesc.Height) return D3DERR_INVALIDCALL;
     }
 
     hr = IDirect3DSurface9_LockRect(pDestSurface, &lockrect, pDestRect, 0);
     if(FAILED(hr)) return D3DXERR_INVALIDDATA;
 
-    copy_simple_data((CONST BYTE*)pSrcMemory, SrcPitch, srcsize, srcformatdesc,
-                     (CONST BYTE*)lockrect.pBits, lockrect.Pitch, destsize, destformatdesc,
-                     dwFilter);
+    /* pretend to support all filters */
+    if((dwFilter & 0xF) == D3DX_FILTER_NONE || 1/*(dwFilter & 0xF) == D3DX_FILTER_POINT*/) {
+        point_filter_simple_data((CONST BYTE*)pSrcMemory + pSrcRect->left * srcformatdesc->bytes_per_pixel + pSrcRect->top * SrcPitch,
+                                 SrcPitch, srcsize, srcformatdesc, (CONST BYTE*)lockrect.pBits, lockrect.Pitch, destsize, destformatdesc,
+                                 dwFilter);
+    } else {
+        /* TODO: Implement D3DX_FILTER_LINEAR, D3DX_FILTER_TRIANGLE and D3DX_FILTER_BOX */
+    }
 
     IDirect3DSurface9_UnlockRect(pDestSurface);
     return D3D_OK;
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c
index f251116..3888b20 100644
--- a/dlls/d3dx9_36/tests/texture.c
+++ b/dlls/d3dx9_36/tests/texture.c
@@ -340,10 +340,8 @@ static void test_D3DXLoadSurface(IDirect3DDevice9 *device)
     /* D3DXLoadSurfaceFromSurface */
     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 256, 256, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &newsurf, NULL);
     if(SUCCEEDED(hr)) {
-        todo_wine {
-            hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_DEFAULT, 0);
-            ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x\n", hr, D3D_OK);
-        }
+        hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_DEFAULT, 0);
+        ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x\n", hr, D3D_OK);
 
         hr = D3DXLoadSurfaceFromSurface(NULL, NULL, NULL, surf, NULL, NULL, D3DX_DEFAULT, 0);
         ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
-- 
1.6.4.2


--------------080503060306090404090108--



More information about the wine-patches mailing list