[1/4] d3dx9: Search for a compatible pixel format in D3DXCheckTextureRequirements.
Matteo Bruni
matteo.mystral at gmail.com
Fri Oct 15 09:02:50 CDT 2010
-------------- next part --------------
From c8368c6433699391905f2d4bf0eb995d5bc662ae Mon Sep 17 00:00:00 2001
From: Matteo Bruni <mbruni at codeweavers.com>
Date: Tue, 5 Oct 2010 21:58:59 +0200
Subject: 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];
+}
--
1.7.2.2
More information about the wine-patches
mailing list