Module: wine Branch: master Commit: ebbf519b782d1523f90c3e6e5bbb9161733daf18 URL: http://source.winehq.org/git/wine.git/?a=commit;h=ebbf519b782d1523f90c3e6e5b...
Author: Matteo Bruni mbruni@codeweavers.com Date: Tue Oct 5 21:58:59 2010 +0200
d3dx9: Search for a compatible pixel format in D3DXCheckTextureRequirements.
---
dlls/d3dx9_36/d3dx9_36_private.h | 2 +- dlls/d3dx9_36/tests/texture.c | 43 +++++++++++++- dlls/d3dx9_36/texture.c | 116 ++++++++++++++++++++++++++++++-------- dlls/d3dx9_36/util.c | 9 +++ 4 files changed, 143 insertions(+), 27 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h index 9598090..6857196 100644 --- a/dlls/d3dx9_36/d3dx9_36_private.h +++ b/dlls/d3dx9_36/d3dx9_36_private.h @@ -48,7 +48,7 @@ HRESULT map_view_of_file(LPCWSTR filename, LPVOID *buffer, DWORD *length); HRESULT load_resource_into_memory(HMODULE module, HRSRC resinfo, LPVOID *buffer, DWORD *length);
const PixelFormatDesc *get_format_info(D3DFORMAT format); - +const PixelFormatDesc *get_format_info_idx(int idx);
extern const ID3DXBufferVtbl D3DXBuffer_Vtbl;
diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 3764089..05ccec4 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -27,9 +27,12 @@ static void test_D3DXCheckTextureRequirements(IDirect3DDevice9 *device) { UINT width, height, mipmaps; - D3DFORMAT format; + D3DFORMAT format, expected; D3DCAPS9 caps; HRESULT hr; + IDirect3D9 *d3d; + D3DDEVICE_CREATION_PARAMETERS params; + D3DDISPLAYMODE mode;
IDirect3DDevice9_GetDeviceCaps(device, &caps);
@@ -145,15 +148,51 @@ static void test_D3DXCheckTextureRequirements(IDirect3DDevice9 *device) ok(hr == D3DERR_INVALIDCALL, "D3DXCheckTextureRequirements succeeded, but should've failed.\n");
/* format */ + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + 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; + format = D3DX_DEFAULT; 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 = D3DFMT_R8G8B8; + 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_X8R8G8B8, "Returned format %u, expected %u\n", format, D3DFMT_X8R8G8B8); + + IDirect3DDevice9_GetDirect3D(device, &d3d); + IDirect3DDevice9_GetCreationParameters(device, ¶ms); + IDirect3DDevice9_GetDisplayMode(device, 0, &mode); + + if(SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, + mode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_R3G3B2))) + expected = D3DFMT_R3G3B2; + else + expected = D3DFMT_X4R4G4B4; + + format = D3DFMT_R3G3B2; + 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 == expected, "Returned format %u, expected %u\n", format, expected); + + if(SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, + mode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R3G3B2))) + expected = D3DFMT_A8R3G3B2; + else + expected = D3DFMT_A8R8G8B8; + + format = D3DFMT_A8R3G3B2; + 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 == expected, "Returned format %u, expected %u\n", format, expected); + + IDirect3D9_Release(d3d); }
static void test_D3DXCreateTexture(IDirect3DDevice9 *device) diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index 2ebc85a..4f7c284 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -122,6 +122,11 @@ HRESULT WINAPI D3DXCheckTextureRequirements(LPDIRECT3DDEVICE9 device, UINT w = (width && *width) ? *width : 1; UINT h = (height && *height) ? *height : 1; D3DCAPS9 caps; + D3DDEVICE_CREATION_PARAMETERS params; + IDirect3D9 *d3d = NULL; + D3DDISPLAYMODE mode; + HRESULT hr; + D3DFORMAT usedformat = D3DFMT_UNKNOWN;
TRACE("(%p, %p, %p, %p, %u, %p, %u)\n", device, width, height, miplevels, usage, format, pool);
@@ -129,8 +134,9 @@ HRESULT WINAPI D3DXCheckTextureRequirements(LPDIRECT3DDEVICE9 device, return D3DERR_INVALIDCALL;
/* usage */ - if ((usage != D3DX_DEFAULT) && - (usage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | D3DUSAGE_NPATCHES))) + if (usage == D3DX_DEFAULT) + usage = 0; + if (usage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | D3DUSAGE_NPATCHES)) return D3DERR_INVALIDCALL;
/* pool */ @@ -202,44 +208,106 @@ HRESULT WINAPI D3DXCheckTextureRequirements(LPDIRECT3DDEVICE9 device, /* format */ if (format) { - D3DDEVICE_CREATION_PARAMETERS params; - IDirect3D9 *d3d = NULL; - D3DDISPLAYMODE mode; - HRESULT hr; + TRACE("Requested format %x\n", *format); + usedformat = *format; + }
- hr = IDirect3DDevice9_GetDirect3D(device, &d3d); + hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
- if (FAILED(hr)) - goto cleanup; + if (FAILED(hr)) + goto cleanup;
- hr = IDirect3DDevice9_GetCreationParameters(device, ¶ms); + hr = IDirect3DDevice9_GetCreationParameters(device, ¶ms);
- if (FAILED(hr)) - goto cleanup; + if (FAILED(hr)) + goto cleanup;
- hr = IDirect3DDevice9_GetDisplayMode(device, 0, &mode); + hr = IDirect3DDevice9_GetDisplayMode(device, 0, &mode);
- if (FAILED(hr)) + if (FAILED(hr)) + goto cleanup; + + if ((usedformat == D3DFMT_UNKNOWN) || (usedformat == D3DX_DEFAULT)) + usedformat = D3DFMT_A8R8G8B8; + + hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, mode.Format, + usage, D3DRTYPE_TEXTURE, usedformat); + + if (FAILED(hr)) + { + /* Heuristic to choose the fallback format */ + const PixelFormatDesc *fmt = get_format_info(usedformat); + BOOL allow_24bits; + int bestscore = INT_MIN, i = 0, j; + unsigned int channels; + const PixelFormatDesc *curfmt; + + if (!fmt) + { + FIXME("Pixel format %x not handled\n", usedformat); goto cleanup; + }
- if ((*format == D3DFMT_UNKNOWN) || (*format == D3DX_DEFAULT)) - *format = D3DFMT_A8R8G8B8; + allow_24bits = fmt->bytes_per_pixel == 3; + channels = (fmt->bits[0] ? 1 : 0) + (fmt->bits[1] ? 1 : 0) + + (fmt->bits[2] ? 1 : 0) + (fmt->bits[3] ? 1 : 0); + usedformat = D3DFMT_UNKNOWN;
- hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, mode.Format, usage, - D3DRTYPE_TEXTURE, *format); + while ((curfmt = get_format_info_idx(i))) + { + unsigned int curchannels = (curfmt->bits[0] ? 1 : 0) + (curfmt->bits[1] ? 1 : 0) + + (curfmt->bits[2] ? 1 : 0) + (curfmt->bits[3] ? 1 : 0); + int score;
- if (FAILED(hr)) - FIXME("Pixel format adjustment not implemented yet\n"); + i++; + + if (curchannels < channels) + continue; + if (curfmt->bytes_per_pixel == 3 && !allow_24bits) + continue; + + hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, + mode.Format, usage, D3DRTYPE_TEXTURE, curfmt->format); + if (FAILED(hr)) + continue; + + /* This format can be used, let's evaluate it. + Weights chosen quite arbitrarily... */ + score = 16 - 4 * (curchannels - channels); + + for (j = 0; j < 4; j++) + { + int diff = curfmt->bits[j] - fmt->bits[j]; + score += 16 - (diff < 0 ? -diff * 4 : diff); + } + + if (score > bestscore) + { + bestscore = score; + usedformat = curfmt->format; + } + } + hr = D3D_OK; + }
cleanup:
- if (d3d) - IDirect3D9_Release(d3d); + if (d3d) + IDirect3D9_Release(d3d);
- if (FAILED(hr)) - return D3DERR_INVALIDCALL; + if (FAILED(hr)) + return hr; + + if (usedformat == D3DFMT_UNKNOWN) + { + WARN("Couldn't find a suitable pixel format\n"); + return D3DERR_NOTAVAILABLE; }
+ TRACE("Format chosen: %x\n", usedformat); + if (format) + *format = usedformat; + return D3D_OK; }
diff --git a/dlls/d3dx9_36/util.c b/dlls/d3dx9_36/util.c index 748e6d1..dc8e820 100644 --- a/dlls/d3dx9_36/util.c +++ b/dlls/d3dx9_36/util.c @@ -152,3 +152,12 @@ const PixelFormatDesc *get_format_info(D3DFORMAT format) while(formats[i].format != format && formats[i].format != D3DFMT_UNKNOWN) i++; return &formats[i]; } + +const PixelFormatDesc *get_format_info_idx(int idx) +{ + if(idx >= sizeof(formats) / sizeof(formats[0])) + return NULL; + if(formats[idx].format == D3DFMT_UNKNOWN) + return NULL; + return &formats[idx]; +}