[PATCH] d3dx9_36: Implement D3DXCheckTextureRequirements + tests (try 2)
Christian Costa
titan.costa at wanadoo.fr
Tue Apr 20 02:03:34 CDT 2010
From: Tony Wasserka <tony.wasserka at freenet.de>
--
Simplify is_pow2 and make_pow2 and move them to util.c for reuse.
Display a FIXME when pixel format adjustment is needed.
Remove refcount checks in tests as well as useless resource.h inclusion.
---
dlls/d3dx9_36/d3dx9_36_private.h | 2
dlls/d3dx9_36/tests/Makefile.in | 3 -
dlls/d3dx9_36/tests/texture.c | 188 ++++++++++++++++++++++++++++++++++++++
dlls/d3dx9_36/texture.c | 98 +++++++++++++++++++-
dlls/d3dx9_36/util.c | 19 ++++
5 files changed, 307 insertions(+), 3 deletions(-)
create mode 100644 dlls/d3dx9_36/tests/texture.c
-------------- next part --------------
diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h
index 275b153..f44780b 100644
--- a/dlls/d3dx9_36/d3dx9_36_private.h
+++ b/dlls/d3dx9_36/d3dx9_36_private.h
@@ -51,6 +51,8 @@ HRESULT load_resource_into_memory(HMODULE module, HRSRC resinfo, LPVOID *buffer,
const PixelFormatDesc *get_format_info(D3DFORMAT format);
+BOOL is_pow2(UINT num);
+UINT make_pow2(UINT num);
extern const ID3DXBufferVtbl D3DXBuffer_Vtbl;
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..9b10c51
--- /dev/null
+++ b/dlls/d3dx9_36/tests/texture.c
@@ -0,0 +1,188 @@
+/*
+ * 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"
+
+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);
+
+ IDirect3DDevice9_Release(device);
+ IDirect3D9_Release(d3d);
+ DestroyWindow(wnd);
+}
diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c
index 9454615..7d3bd91 100644
--- a/dlls/d3dx9_36/texture.c
+++ b/dlls/d3dx9_36/texture.c
@@ -29,9 +29,103 @@ 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, ¶ms);
+ 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 (FAILED(hr))
+ FIXME("Pixel format adjustment not implemented yet\n");
+ }
+
+ if (d3d)
+ IDirect3D9_Release(d3d);
+
+ if (FAILED(hr))
+ return D3DERR_INVALIDCALL;
+ }
+
+ return D3D_OK;
}
HRESULT WINAPI D3DXCreateTexture(LPDIRECT3DDEVICE9 pDevice,
diff --git a/dlls/d3dx9_36/util.c b/dlls/d3dx9_36/util.c
index 748e6d1..c7f6b7f 100644
--- a/dlls/d3dx9_36/util.c
+++ b/dlls/d3dx9_36/util.c
@@ -152,3 +152,22 @@ const PixelFormatDesc *get_format_info(D3DFORMAT format)
while(formats[i].format != format && formats[i].format != D3DFMT_UNKNOWN) i++;
return &formats[i];
}
+
+/* Return TRUE if num is a power of 2, FALSE otherwise */
+BOOL is_pow2(UINT num)
+{
+ if (!num) return FALSE;
+
+ return !(num & (num - 1));
+}
+
+/* Returns the smallest power of 2 which is greater than or equal num */
+UINT make_pow2(UINT num)
+{
+ UINT result = 1;
+
+ while (result < num)
+ result <<= 1;
+
+ return result;
+}
More information about the wine-patches
mailing list