[2/3] d3dx9: Implement D3DXFillCubeTexture function.

Matteo Bruni matteo.mystral at gmail.com
Wed Nov 17 10:23:39 CST 2010


-------------- next part --------------
From 02de99d621816e0f22ed35acddd2c7ce59b1e388 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <mbruni at codeweavers.com>
Date: Sat, 13 Nov 2010 00:05:11 +0100
Subject: d3dx9: Implement D3DXFillCubeTexture function.

---
 dlls/d3dx9_36/d3dx9_36.spec   |    2 +-
 dlls/d3dx9_36/tests/texture.c |  157 +++++++++++++++++++++++++++++++++++++++++
 dlls/d3dx9_36/texture.c       |  135 +++++++++++++++++++++++++++++++++++
 3 files changed, 293 insertions(+), 1 deletions(-)

diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec
index 43362aa..327c406 100644
--- a/dlls/d3dx9_36/d3dx9_36.spec
+++ b/dlls/d3dx9_36/d3dx9_36.spec
@@ -122,7 +122,7 @@
 @ stub D3DXDisassembleEffect
 @ stub D3DXDisassembleShader
 @ stub D3DXFileCreate
-@ stub D3DXFillCubeTexture
+@ stdcall D3DXFillCubeTexture(ptr ptr ptr)
 @ stub D3DXFillCubeTextureTX
 @ stdcall D3DXFillTexture(ptr ptr ptr)
 @ stub D3DXFillTextureTX
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c
index 6f7003a..791d2f9 100644
--- a/dlls/d3dx9_36/tests/texture.c
+++ b/dlls/d3dx9_36/tests/texture.c
@@ -776,6 +776,162 @@ static void test_D3DXFillTexture(IDirect3DDevice9 *device)
     IDirect3DTexture9_Release(tex);
 }
 
+static void WINAPI fillfunc_cube(D3DXVECTOR4 *value, const D3DXVECTOR3 *texcoord,
+                                 const D3DXVECTOR3 *texelsize, void *data)
+{
+    value->x = (texcoord->x + 1.0f) / 2.0f;
+    value->y = (texcoord->y + 1.0f) / 2.0f;
+    value->z = (texcoord->z + 1.0f) / 2.0f;
+    value->w = texelsize->x;
+}
+
+enum cube_coord
+{
+    XCOORD = 0,
+    XCOORDINV = 1,
+    YCOORD = 2,
+    YCOORDINV = 3,
+    ZERO = 4,
+    ONE = 5
+};
+
+static float get_cube_coord(enum cube_coord coord, unsigned int x, unsigned int y, unsigned int size)
+{
+    switch (coord)
+    {
+        case XCOORD:
+            return x + 0.5f;
+        case XCOORDINV:
+            return size - x - 0.5f;
+        case YCOORD:
+            return y + 0.5f;
+        case YCOORDINV:
+            return size - y - 0.5f;
+        case ZERO:
+            return 0.0f;
+        case ONE:
+            return size;
+        default:
+           trace("Unexpected coordinate value\n");
+           return 0.0f;
+    }
+}
+
+static void test_D3DXFillCubeTexture(IDirect3DDevice9 *device)
+{
+    IDirect3DCubeTexture9 *tex;
+    HRESULT hr;
+    D3DLOCKED_RECT lock_rect;
+    unsigned int x, y, f, m;
+    unsigned int v[4], e[4];
+    unsigned int value, expected, size, pitch;
+    enum cube_coord coordmap[6][3] =
+        {
+            {ONE, YCOORDINV, XCOORDINV},
+            {ZERO, YCOORDINV, XCOORD},
+            {XCOORD, ONE, YCOORD},
+            {XCOORD, ZERO, YCOORDINV},
+            {XCOORD, YCOORDINV, ONE},
+            {XCOORDINV, YCOORDINV, ZERO}
+        };
+
+    size = 4;
+    hr = IDirect3DDevice9_CreateCubeTexture(device, size, 0, 0, D3DFMT_A8R8G8B8,
+                                            D3DPOOL_MANAGED, &tex, NULL);
+
+    if (SUCCEEDED(hr))
+    {
+        hr = D3DXFillCubeTexture(tex, fillfunc_cube, NULL);
+        ok(hr == D3D_OK, "D3DXFillCubeTexture returned %#x, expected %#x\n", hr, D3D_OK);
+
+        for (m = 0; m < 3; m++)
+        {
+            for (f = 0; f < 6; f++)
+            {
+                hr = IDirect3DCubeTexture9_LockRect(tex, f, m, &lock_rect, NULL, D3DLOCK_READONLY);
+                ok(hr == D3D_OK, "Couldn't lock the texture, error %#x\n", hr);
+                if (SUCCEEDED(hr))
+                {
+                    pitch = lock_rect.Pitch / sizeof(DWORD);
+                    for (y = 0; y < size; y++)
+                    {
+                        for (x = 0; x < size; x++)
+                        {
+                            value = ((DWORD *)lock_rect.pBits)[y * pitch + x];
+                            v[0] = (value >> 24) & 0xff;
+                            v[1] = (value >> 16) & 0xff;
+                            v[2] = (value >> 8) & 0xff;
+                            v[3] = value & 0xff;
+
+                            e[0] = (f == 0) || (f == 1) ?
+                                0 : (unsigned char)(255.0f / size * 2.0f + 0.5f);
+                            e[1] = get_cube_coord(coordmap[f][0], x, y, size) / size * 255.0f + 0.5f;
+                            e[2] = get_cube_coord(coordmap[f][1], x, y, size) / size * 255.0f + 0.5f;
+                            e[3] = get_cube_coord(coordmap[f][2], x, y, size) / size * 255.0f + 0.5f;
+                            expected = e[0] << 24 | e[1] << 16 | e[2] << 8 | e[3];
+
+                            ok(color_match(v, e),
+                               "Texel at face %u (%u, %u) doesn't match: %#x, expected %#x\n",
+                               f, x, y, value, expected);
+                        }
+                    }
+                    IDirect3DCubeTexture9_UnlockRect(tex, f, m);
+                }
+            }
+            size >>= 1;
+        }
+    }
+    else
+        skip("Failed to create texture\n");
+
+    IDirect3DCubeTexture9_Release(tex);
+
+    hr = IDirect3DDevice9_CreateCubeTexture(device, 4, 1, 0, D3DFMT_A1R5G5B5,
+                                            D3DPOOL_MANAGED, &tex, NULL);
+
+    if (SUCCEEDED(hr))
+    {
+        hr = D3DXFillCubeTexture(tex, fillfunc_cube, NULL);
+        ok(hr == D3D_OK, "D3DXFillTexture returned %#x, expected %#x\n", hr, D3D_OK);
+        for (f = 0; f < 6; f++)
+        {
+            hr = IDirect3DCubeTexture9_LockRect(tex, f, 0, &lock_rect, NULL, D3DLOCK_READONLY);
+            ok(hr == D3D_OK, "Couldn't lock the texture, error %#x\n", hr);
+            if (SUCCEEDED(hr))
+            {
+                pitch = lock_rect.Pitch / sizeof(WORD);
+                for (y = 0; y < 4; y++)
+                {
+                    for (x = 0; x < 4; x++)
+                    {
+                        value = ((WORD *)lock_rect.pBits)[y * pitch + x];
+                        v[0] = value >> 15;
+                        v[1] = value >> 10 & 0x1f;
+                        v[2] = value >> 5 & 0x1f;
+                        v[3] = value & 0x1f;
+
+                        e[0] = (f == 0) || (f == 1) ?
+                            0 : (unsigned char)(1.0f / size * 2.0f + 0.5f);
+                        e[1] = get_cube_coord(coordmap[f][0], x, y, 4) / 4 * 31.0f + 0.5f;
+                        e[2] = get_cube_coord(coordmap[f][1], x, y, 4) / 4 * 31.0f + 0.5f;
+                        e[3] = get_cube_coord(coordmap[f][2], x, y, 4) / 4 * 31.0f + 0.5f;
+                        expected = e[0] << 15 | e[1] << 10 | e[2] << 5 | e[3];
+
+                        ok(color_match(v, e),
+                           "Texel at face %u (%u, %u) doesn't match: %#x, expected %#x\n",
+                           f, x, y, value, expected);
+                    }
+                }
+                IDirect3DCubeTexture9_UnlockRect(tex, f, 0);
+            }
+        }
+    }
+    else
+        skip("Failed to create texture\n");
+
+    IDirect3DCubeTexture9_Release(tex);
+}
+
 START_TEST(texture)
 {
     HWND wnd;
@@ -813,6 +969,7 @@ START_TEST(texture)
     test_D3DXCreateTexture(device);
     test_D3DXFilterTexture(device);
     test_D3DXFillTexture(device);
+    test_D3DXFillCubeTexture(device);
 
     IDirect3DDevice9_Release(device);
     IDirect3D9_Release(d3d);
diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c
index da36710..39351c9 100644
--- a/dlls/d3dx9_36/texture.c
+++ b/dlls/d3dx9_36/texture.c
@@ -1028,3 +1028,138 @@ HRESULT WINAPI D3DXFillTexture(LPDIRECT3DTEXTURE9 texture,
 
     return D3D_OK;
 }
+
+enum cube_coord
+{
+    XCOORD = 0,
+    XCOORDINV = 1,
+    YCOORD = 2,
+    YCOORDINV = 3,
+    ZERO = 4,
+    ONE = 5
+};
+
+static float get_cube_coord(enum cube_coord coord, unsigned int x, unsigned int y, unsigned int size)
+{
+    switch (coord)
+    {
+        case XCOORD:
+            return x + 0.5f;
+        case XCOORDINV:
+            return size - x - 0.5f;
+        case YCOORD:
+            return y + 0.5f;
+        case YCOORDINV:
+            return size - y - 0.5f;
+        case ZERO:
+            return 0.0f;
+        case ONE:
+            return size;
+       default:
+           ERR("Unexpected coordinate value\n");
+           return 0.0f;
+    }
+}
+
+HRESULT WINAPI D3DXFillCubeTexture(LPDIRECT3DCUBETEXTURE9 texture,
+                                   LPD3DXFILL3D function,
+                                   LPVOID funcdata)
+{
+    DWORD miplevels;
+    DWORD m, i, x, y, c, f, v;
+    D3DSURFACE_DESC desc;
+    D3DLOCKED_RECT lock_rect;
+    D3DXVECTOR4 value;
+    D3DXVECTOR3 coord, size;
+    const PixelFormatDesc *format;
+    unsigned char *data, *pos;
+    unsigned char byte, mask;
+    float comp_value;
+    const static enum cube_coord coordmap[6][3] =
+        {
+            {ONE, YCOORDINV, XCOORDINV},
+            {ZERO, YCOORDINV, XCOORD},
+            {XCOORD, ONE, YCOORD},
+            {XCOORD, ZERO, YCOORDINV},
+            {XCOORD, YCOORDINV, ONE},
+            {XCOORDINV, YCOORDINV, ZERO}
+        };
+
+    if (texture == NULL || function == NULL)
+        return D3DERR_INVALIDCALL;
+
+    miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
+
+    for (m = 0; m < miplevels; m++)
+    {
+        if (FAILED(IDirect3DCubeTexture9_GetLevelDesc(texture, m, &desc)))
+            return D3DERR_INVALIDCALL;
+
+        format = get_format_info(desc.Format);
+        if (format->format == D3DFMT_UNKNOWN)
+        {
+            FIXME("Unsupported texture format %#x\n", desc.Format);
+            return D3DERR_INVALIDCALL;
+        }
+
+        for (f = 0; f < 6; f++)
+        {
+            if (FAILED(IDirect3DCubeTexture9_LockRect(texture, f, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
+                return D3DERR_INVALIDCALL;
+
+            size.x = (f == 0) || (f == 1) ? 0.0f : 2.0f / desc.Width;
+            size.y = (f == 2) || (f == 3) ? 0.0f : 2.0f / desc.Width;
+            size.z = (f == 4) || (f == 5) ? 0.0f : 2.0f / desc.Width;
+
+            data = lock_rect.pBits;
+
+            for (y = 0; y < desc.Height; y++)
+            {
+                for (x = 0; x < desc.Width; x++)
+                {
+                    coord.x = get_cube_coord(coordmap[f][0], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
+                    coord.y = get_cube_coord(coordmap[f][1], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
+                    coord.z = get_cube_coord(coordmap[f][2], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
+
+                    function(&value, &coord, &size, funcdata);
+
+                    pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
+
+                    for (i = 0; i < format->bytes_per_pixel; i++)
+                        pos[i] = 0;
+
+                    for (c = 0; c < 4; c++)
+                    {
+                        switch (c)
+                        {
+                            case 0: /* Alpha */
+                                comp_value = value.w;
+                                break;
+                            case 1: /* Red */
+                                comp_value = value.x;
+                                break;
+                            case 2: /* Green */
+                                comp_value = value.y;
+                                break;
+                            case 3: /* Blue */
+                                comp_value = value.z;
+                                break;
+                        }
+
+                        v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
+
+                        for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
+                        {
+                            mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
+                            byte = (v << format->shift[c] >> i) & mask;
+                            pos[i / 8] |= byte;
+                        }
+                    }
+                }
+            }
+            IDirect3DCubeTexture9_UnlockRect(texture, f, m);
+        }
+    }
+
+    return D3D_OK;
+}
-- 
1.7.2.2


More information about the wine-patches mailing list