[PATCH] d3dx9_36: Implement D3DXCheckTextureRequirements + tests

Christian Costa titan.costa at wanadoo.fr
Mon Apr 19 02:43:56 CDT 2010


From: Tony Wasserka <tony.wasserka at freenet.de>


---

 dlls/d3dx9_36/tests/Makefile.in |    3 -
 dlls/d3dx9_36/tests/texture.c   |  207 +++++++++++++++++++++++++++++++++++++++
 dlls/d3dx9_36/texture.c         |  118 ++++++++++++++++++++++
 3 files changed, 325 insertions(+), 3 deletions(-)
 create mode 100644 dlls/d3dx9_36/tests/texture.c
-------------- next part --------------
diff --git a/dlls/d3dx9_36/tests/Makefile.in b/dlls/d3dx9_36/tests/Makefile.in
index b9ad40d..fda718c 100644
--- a/dlls/d3dx9_36/tests/Makefile.in
+++ b/dlls/d3dx9_36/tests/Makefile.in
@@ -13,7 +13,8 @@ C_SRCS = \
 	math.c \
 	mesh.c \
 	shader.c \
-	surface.c
+	surface.c \
+	texture.c
 
 RC_SRCS = rsrc.rc
 
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c
new file mode 100644
index 0000000..fe7a338
--- /dev/null
+++ b/dlls/d3dx9_36/tests/texture.c
@@ -0,0 +1,207 @@
+/*
+ * Tests for the D3DX9 texture functions
+ *
+ * Copyright 2009 Tony Wasserka
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+#include "wine/test.h"
+#include "d3dx9tex.h"
+#include "resources.h"
+
+static inline int get_ref(IUnknown *obj)
+{
+    IUnknown_AddRef(obj);
+    return IUnknown_Release(obj);
+}
+
+static inline void check_ref(IUnknown *obj, int exp)
+{
+    int ref = get_ref(obj);
+    ok (exp == ref, "Invalid refcount. Expected %d, got %d\n", exp, ref);
+}
+
+static inline void check_release(IUnknown *obj, int exp)
+{
+    int ref = IUnknown_Release(obj);
+    ok (ref == exp, "Invalid refcount. Expected %d, got %d\n", exp, ref);
+}
+
+static void test_D3DXCheckTextureRequirements(IDirect3DDevice9 *device)
+{
+    HRESULT hr;
+    D3DCAPS9 caps;
+    UINT width, height, mipmaps;
+    D3DFORMAT format;
+
+    IDirect3DDevice9_GetDeviceCaps(device, &caps);
+
+    /* general tests */
+    hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+
+    hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, D3DX_DEFAULT, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+
+    hr = D3DXCheckTextureRequirements(NULL, NULL, NULL, NULL, D3DX_DEFAULT, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3DERR_INVALIDCALL, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
+
+    /* width & height */
+    width = height = D3DX_DEFAULT;
+    hr = D3DXCheckTextureRequirements(device, &width, &height, NULL, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(width == 256, "Returned width %d, expected %d\n", width, 256);
+    ok(height == 256, "Returned height %d, expected %d\n", height, 256);
+
+    width = D3DX_DEFAULT;
+    hr = D3DXCheckTextureRequirements(device, &width, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(width == 256, "Returned width %d, expected %d\n", width, 256);
+
+    width = 62;
+    hr = D3DXCheckTextureRequirements(device, &width, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(width == 62, "Returned width %d, expected %d\n", width, 62);
+
+    width = D3DX_DEFAULT; height = 63;
+    hr = D3DXCheckTextureRequirements(device, &width, &height, NULL, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(width == height, "Returned width %d, expected %d\n", width, height);
+    ok(height == 63, "Returned height %d, expected %d\n", height, 63);
+
+    width = D3DX_DEFAULT; height = 0;
+    hr = D3DXCheckTextureRequirements(device, &width, &height, NULL, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(width == 1, "Returned width %d, expected %d\n", width, 1);
+    ok(height == 1, "Returned height %d, expected %d\n", height, 1);
+
+    width = 0; height = 0;
+    hr = D3DXCheckTextureRequirements(device, &width, &height, NULL, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(width == 1, "Returned width %d, expected %d\n", width, 1);
+    ok(height == 1, "Returned height %d, expected %d\n", height, 1);
+
+    width = 0;
+    hr = D3DXCheckTextureRequirements(device, &width, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(width == 1, "Returned width %d, expected %d\n", width, 1);
+
+    width = D3DX_DEFAULT;
+    hr = D3DXCheckTextureRequirements(device, &width, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(width == 256, "Returned width %d, expected %d\n", width, 256);
+
+    width = 0xFFFFFFFE;
+    hr = D3DXCheckTextureRequirements(device, &width, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(width == caps.MaxTextureWidth, "Returned width %d, expected %d\n", width, caps.MaxTextureWidth);
+
+    width = caps.MaxTextureWidth-1;
+    hr = D3DXCheckTextureRequirements(device, &width, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(width == caps.MaxTextureWidth-1, "Returned width %d, expected %d\n", width, caps.MaxTextureWidth-1);
+
+    /* mipmaps */
+    width = 64; height = 63;
+    mipmaps = 9;
+    hr = D3DXCheckTextureRequirements(device, &width, &height, &mipmaps, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(mipmaps == 7, "Returned mipmaps %d, expected %d\n", mipmaps, 7);
+
+    width = 284; height = 137;
+    mipmaps = 20;
+    hr = D3DXCheckTextureRequirements(device, &width, &height, &mipmaps, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(mipmaps == 9, "Returned mipmaps %d, expected %d\n", mipmaps, 9);
+
+    width = height = 63;
+    mipmaps = 9;
+    hr = D3DXCheckTextureRequirements(device, &width, &height, &mipmaps, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(mipmaps == 6, "Returned mipmaps %d, expected %d\n", mipmaps, 6);
+
+    mipmaps = 20;
+    hr = D3DXCheckTextureRequirements(device, NULL, NULL, &mipmaps, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(mipmaps == 9, "Returned mipmaps %d, expected %d\n", mipmaps, 9);
+
+    mipmaps = 0;
+    hr = D3DXCheckTextureRequirements(device, NULL, NULL, &mipmaps, 0, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(mipmaps == 9, "Returned mipmaps %d, expected %d\n", mipmaps, 9);
+
+    /* usage */
+    hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, D3DUSAGE_WRITEONLY, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3DERR_INVALIDCALL, "D3DXCheckTextureRequirements succeeded, but should've failed.\n");
+    hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, D3DUSAGE_DONOTCLIP, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3DERR_INVALIDCALL, "D3DXCheckTextureRequirements succeeded, but should've failed.\n");
+    hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, D3DUSAGE_POINTS, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3DERR_INVALIDCALL, "D3DXCheckTextureRequirements succeeded, but should've failed.\n");
+    hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, D3DUSAGE_RTPATCHES, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3DERR_INVALIDCALL, "D3DXCheckTextureRequirements succeeded, but should've failed.\n");
+    hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, D3DUSAGE_NPATCHES, NULL, D3DPOOL_DEFAULT);
+    ok(hr == D3DERR_INVALIDCALL, "D3DXCheckTextureRequirements succeeded, but should've failed.\n");
+
+    /* format */
+    format = D3DFMT_UNKNOWN;
+    hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, 0, &format, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u\n", format, D3DFMT_A8R8G8B8);
+
+    format = 0;
+    hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, 0, &format, D3DPOOL_DEFAULT);
+    ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK);
+    ok(format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u\n", format, D3DFMT_A8R8G8B8);
+}
+
+START_TEST(texture)
+{
+    HWND wnd;
+    IDirect3D9 *d3d;
+    IDirect3DDevice9 *device;
+    D3DPRESENT_PARAMETERS d3dpp;
+    HRESULT hr;
+
+    wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
+    if (!wnd) {
+        skip("Couldn't create application window\n");
+        return;
+    }
+    d3d = Direct3DCreate9(D3D_SDK_VERSION);
+    if (!d3d) {
+        skip("Couldn't create IDirect3D9 object\n");
+        DestroyWindow(wnd);
+        return;
+    }
+
+    ZeroMemory(&d3dpp, sizeof(d3dpp));
+    d3dpp.Windowed   = TRUE;
+    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+    hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
+    if (FAILED(hr)) {
+        skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
+        IDirect3D9_Release(d3d);
+        DestroyWindow(wnd);
+        return;
+    }
+
+    test_D3DXCheckTextureRequirements(device);
+
+    check_release((IUnknown*)device, 0);
+    check_release((IUnknown*)d3d, 0);
+    DestroyWindow(wnd);
+}
diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c
index 9454615..d9c22cb 100644
--- a/dlls/d3dx9_36/texture.c
+++ b/dlls/d3dx9_36/texture.c
@@ -21,6 +21,29 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
+/* Return TRUE if num is a power of 2, FALSE otherwise */
+BOOL is_pow2(UINT num)
+{
+    UINT i;
+
+    if (!num) return FALSE;
+    for (i = 0; num >> 1; i++) num >>= 1;
+
+    return (num << i) == num;
+}
+
+/* Returns the smallest power of 2 which is greater than or equal num */
+UINT make_pow2(UINT num)
+{
+    UINT i;
+
+    for(i = 0; i < 8 * sizeof(UINT); i++)
+        if ((1 << i) >= num)
+            return 1 << i;
+
+    return 0;
+}
+
 HRESULT WINAPI D3DXCheckTextureRequirements(LPDIRECT3DDEVICE9 device,
                                             UINT* width,
                                             UINT* height,
@@ -29,9 +52,100 @@ HRESULT WINAPI D3DXCheckTextureRequirements(LPDIRECT3DDEVICE9 device,
                                             D3DFORMAT* format,
                                             D3DPOOL pool)
 {
-    FIXME("(%p, %p, %p, %p, %u, %p, %u): stub\n", device, width, height, miplevels, usage, format, pool);
+    D3DCAPS9 caps;
 
-    return E_NOTIMPL;
+    TRACE("(%p, %p, %p, %p, %u, %p, %u)\n", device, width, height, miplevels, usage, format, pool);
+
+    if (!device)
+        return D3DERR_INVALIDCALL;
+
+    /* usage */
+    if (usage != D3DX_DEFAULT &&
+        usage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | D3DUSAGE_NPATCHES))
+        return D3DERR_INVALIDCALL;
+
+    /* pool */
+    if (pool != D3DPOOL_DEFAULT && pool != D3DPOOL_MANAGED && pool != D3DPOOL_SYSTEMMEM && pool != D3DPOOL_SCRATCH)
+        return D3DERR_INVALIDCALL;
+
+    /* width and height */
+    IDirect3DDevice9_GetDeviceCaps(device, &caps);
+    if (width && height) {
+        if (*width == D3DX_DEFAULT && *height == D3DX_DEFAULT) *width = *height = 256;
+        else if (*width == D3DX_DEFAULT) *width = *height;
+        else if (*height == D3DX_DEFAULT) *height = *width;
+
+        if (*width == 0) *width = 1;
+        if (*height == 0) *height = 1;
+    } else if (width) {
+        if (*width == D3DX_DEFAULT) *width = 256;
+        else if (*width == 0) *width = 1;
+    } else if (height) {
+        if (*height == D3DX_DEFAULT) *height = 256;
+        else if (*height == 0) *height = 1;
+    }
+
+    if (width) {
+        if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && !is_pow2(*width)) make_pow2(*width);
+        if (*width > caps.MaxTextureWidth) *width = caps.MaxTextureWidth;
+    }
+    if (height) {
+        if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && !is_pow2(*height)) make_pow2(*height);
+        if (*height > caps.MaxTextureHeight) *height = caps.MaxTextureHeight;
+    }
+    if (width && height && (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)) {
+        if (*width > *height) *height = *width;
+        else *width = *height;
+    }
+
+    /* miplevels */
+    if (miplevels) {
+        UINT max_mipmaps = 1;
+
+        if (!width && !height)
+            max_mipmaps = 9;
+        else {
+            UINT buf_width = width ? *width : 1;
+            UINT buf_height = height ? *height : 1;
+
+            while (buf_width > 1 || buf_height > 1) {
+                buf_width >>= 1;
+                buf_height >>= 1;
+                max_mipmaps++;
+            }
+        }
+        if (*miplevels == 0 || *miplevels > max_mipmaps)
+            *miplevels = max_mipmaps;
+    }
+
+    /* format */
+    if (format) {
+        IDirect3D9 *d3d = NULL;
+        D3DDEVICE_CREATION_PARAMETERS params;
+        D3DDISPLAYMODE mode;
+        HRESULT hr;
+
+        hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
+        if (SUCCEEDED(hr))
+            IDirect3DDevice9_GetCreationParameters(device, &params);
+        if (SUCCEEDED(hr))
+            IDirect3DDevice9_GetDisplayMode(device, 0, &mode);
+
+        if (SUCCEEDED(hr)) {
+            if (*format == D3DFMT_UNKNOWN || *format == D3DX_DEFAULT) *format = D3DFMT_A8R8G8B8;
+
+            hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, mode.Format, usage,
+                D3DRTYPE_TEXTURE, *format);
+        }
+
+        if (d3d)
+            IDirect3D9_Release(d3d);
+
+        if (FAILED(hr))
+            return D3DERR_INVALIDCALL;
+    }
+
+    return D3D_OK;
 }
 
 HRESULT WINAPI D3DXCreateTexture(LPDIRECT3DDEVICE9 pDevice,


More information about the wine-patches mailing list