From b5c7675dd32cc9b5384583848a0cec5e4ad09a6b Mon Sep 17 00:00:00 2001 From: Owen Rudge Date: Thu, 22 Jul 2010 20:38:04 +0100 Subject: [PATCH] d3dx9: Implement D3DXCheckTextureRequirements. --- dlls/d3dx9_36/tests/texture.c | 4 - dlls/d3dx9_36/texture.c | 146 +++++++++++++++++++++++++++++++++- 2 files changed, 144 insertions(+), 6 deletions(-) diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index de7ccf4a140..15b3e78cd8f 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -27,8 +27,6 @@ static void test_D3DXCheckTextureRequirements(IDirect3DDevice9 *device) { HRESULT hr; - todo_wine { - /* 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); @@ -38,8 +36,6 @@ static void test_D3DXCheckTextureRequirements(IDirect3DDevice9 *device) hr = D3DXCheckTextureRequirements(NULL, NULL, NULL, NULL, D3DX_DEFAULT, NULL, D3DPOOL_DEFAULT); ok(hr == D3DERR_INVALIDCALL, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); - - } /* todo_wine */ } START_TEST(texture) diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index 9454615f89c..ad3a1c2bea1 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -1,5 +1,7 @@ /* + * Copyright 2009 Tony Wasserka * Copyright 2010 Christian Costa + * Copyright 2010 Owen Rudge for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,6 +23,27 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3dx); +/* Returns TRUE if num is a power of 2, FALSE if not, or if 0 */ +BOOL is_pow2(UINT num) +{ + return !(num & (num - 1)); +} + +/* Returns the smallest power of 2 which is greater than or equal to num */ +UINT make_pow2(UINT num) +{ + UINT result = 1; + + /* In the unlikely event somebody passes a large value, make sure we don't enter an infinite loop */ + if (num >= 0x80000000) + return 0x80000000; + + while (result < num) + result <<= 1; + + return result; +} + HRESULT WINAPI D3DXCheckTextureRequirements(LPDIRECT3DDEVICE9 device, UINT* width, UINT* height, @@ -29,9 +52,128 @@ 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); + UINT w = (width && *width) ? *width : 1; + UINT h = (height && *height) ? *height : 1; + 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 */ + if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps))) + return D3DERR_INVALIDCALL; + + /* 256 x 256 default width/height */ + if ((w == D3DX_DEFAULT) && (h == D3DX_DEFAULT)) + w = h = 256; + else if (w == D3DX_DEFAULT) + w = (height ? h : 256); + else if (h == D3DX_DEFAULT) + h = (width ? w : 256); + + /* ensure width/height is power of 2 */ + if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(w))) + w = make_pow2(w); + + if (w > caps.MaxTextureWidth) + w = caps.MaxTextureWidth; + + if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(h))) + h = make_pow2(h); + + if (h > caps.MaxTextureHeight) + h = caps.MaxTextureHeight; + + /* texture must be square? */ + if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) + { + if (w > h) + h = w; + else + w = h; + } + + if (width) + *width = w; + + if (height) + *height = h; + + /* miplevels */ + if (miplevels) + { + UINT max_mipmaps = 1; + + if (!width && !height) + max_mipmaps = 9; /* number of mipmaps in a 256x256 texture */ + else + { + UINT max_dimen = max(w, h); + + while (max_dimen > 1) + { + max_dimen >>= 1; + max_mipmaps++; + } + } + + if (*miplevels == 0 || *miplevels > max_mipmaps) + *miplevels = max_mipmaps; + } + + /* format */ + if (format) + { + D3DDEVICE_CREATION_PARAMETERS params; + IDirect3D9 *d3d = NULL; + D3DDISPLAYMODE mode; + HRESULT hr; + + hr = IDirect3DDevice9_GetDirect3D(device, &d3d); + + if (FAILED(hr)) + goto cleanup; + + hr = IDirect3DDevice9_GetCreationParameters(device, ¶ms); + + if (FAILED(hr)) + goto cleanup; + + hr = IDirect3DDevice9_GetDisplayMode(device, 0, &mode); + + if (FAILED(hr)) + goto cleanup; + + 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"); + +cleanup: + + if (d3d) + IDirect3D9_Release(d3d); + + if (FAILED(hr)) + return D3DERR_INVALIDCALL; + } + + return D3D_OK; } HRESULT WINAPI D3DXCreateTexture(LPDIRECT3DDEVICE9 pDevice,