Commit 4ac1b94d authored by Roderick Colenbrander's avatar Roderick Colenbrander Committed by Alexandre Julliard

wined3d: Improved CheckDeviceType.

parent d66b9f7e
......@@ -1867,6 +1867,125 @@ cleanup:
if(d3d9) IDirect3D9_Release(d3d9);
}
struct formats {
D3DFORMAT DisplayFormat;
D3DFORMAT BackBufferFormat;
BOOL shouldPass;
};
struct formats r5g6b5_format_list[] =
{
{ D3DFMT_R5G6B5, D3DFMT_R5G6B5, TRUE },
{ D3DFMT_R5G6B5, D3DFMT_X1R5G5B5, FALSE },
{ D3DFMT_R5G6B5, D3DFMT_A1R5G5B5, FALSE },
{ D3DFMT_R5G6B5, D3DFMT_X8R8G8B8, FALSE },
{ D3DFMT_R5G6B5, D3DFMT_A8R8G8B8, FALSE },
{ 0, 0, 0}
};
struct formats x1r5g5b5_format_list[] =
{
{ D3DFMT_X1R5G5B5, D3DFMT_R5G6B5, FALSE },
{ D3DFMT_X1R5G5B5, D3DFMT_X1R5G5B5, TRUE },
{ D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE },
{ D3DFMT_X1R5G5B5, D3DFMT_X8R8G8B8, FALSE },
{ D3DFMT_X1R5G5B5, D3DFMT_A8R8G8B8, FALSE },
/* A1R5G5B5 should not be usable as a display format, it is backbuffer-only */
{ D3DFMT_A1R5G5B5, D3DFMT_R5G6B5, FALSE },
{ D3DFMT_A1R5G5B5, D3DFMT_X1R5G5B5, FALSE },
{ D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE },
{ D3DFMT_A1R5G5B5, D3DFMT_X8R8G8B8, FALSE },
{ D3DFMT_A1R5G5B5, D3DFMT_A8R8G8B8, FALSE },
{ 0, 0, 0}
};
struct formats x8r8g8b8_format_list[] =
{
{ D3DFMT_X8R8G8B8, D3DFMT_R5G6B5, FALSE },
{ D3DFMT_X8R8G8B8, D3DFMT_X1R5G5B5, FALSE },
{ D3DFMT_X8R8G8B8, D3DFMT_A1R5G5B5, FALSE },
{ D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, TRUE },
{ D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE },
/* A1R8G8B8 should not be usable as a display format, it is backbuffer-only */
{ D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, FALSE },
{ D3DFMT_A8R8G8B8, D3DFMT_X1R5G5B5, FALSE },
{ D3DFMT_A8R8G8B8, D3DFMT_A1R5G5B5, FALSE },
{ D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8, FALSE },
{ D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE },
{ 0, 0, 0}
};
static void test_display_formats()
{
/* Direct3D9 offers 4 display formats R5G6B5, X1R5G5B5, X8R8G8B8 and A2R10G10B10.
* Next to these there are 6 different backbuffer formats. Only a fixed number of
* mixings are possible in FULLSCREEN mode. In windowed mode more combinations are
* allowed due to depth conversion and this is likely driver dependent.
* This test checks which combinations are possible in fullscreen mode and this should not be driver dependent.
* TODO: handle A2R10G10B10 but what hardware supports it? Parhelia? It is very rare. */
UINT Adapter = D3DADAPTER_DEFAULT;
D3DDEVTYPE DeviceType = D3DDEVTYPE_HAL;
int i, nmodes;
HRESULT hr;
IDirect3D9 *d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
if(!d3d9) return;
nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_R5G6B5);
if(!nmodes) {
skip("Display format R5G6B5 not supported, skipping\n");
} else {
trace("Testing display format R5G6B5\n");
for(i=0; r5g6b5_format_list[i].DisplayFormat != 0; i++)
{
hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat, FALSE);
if(r5g6b5_format_list[i].shouldPass)
ok(hr == D3D_OK, "format %d %d didn't pass with hr=%#08x\n", r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat, hr);
else
ok(hr != D3D_OK, "format %d %d didn't pass while it was expected to\n", r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat);
}
}
nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X1R5G5B5);
if(!nmodes) {
skip("Display format X1R5G5B5 not supported, skipping\n");
} else {
trace("Testing display format X1R5G5B5\n");
for(i=0; x1r5g5b5_format_list[i].DisplayFormat != 0; i++)
{
hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, x1r5g5b5_format_list[i].DisplayFormat, x1r5g5b5_format_list[i].BackBufferFormat, FALSE);
if(x1r5g5b5_format_list[i].shouldPass)
ok(hr == D3D_OK, "format %d %d didn't pass with hr=%#08x\n", x1r5g5b5_format_list[i].DisplayFormat, x1r5g5b5_format_list[i].BackBufferFormat, hr);
else
ok(hr != D3D_OK, "format %d %d didn't pass while it was expected to\n", x1r5g5b5_format_list[i].DisplayFormat, x1r5g5b5_format_list[i].BackBufferFormat);
}
}
nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
if(!nmodes) {
skip("Display format X8R8G8B8 not supported, skipping\n");
} else {
trace("Testing display format X8R8G8B8\n");
for(i=0; x8r8g8b8_format_list[i].DisplayFormat != 0; i++)
{
hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat, FALSE);
if(x8r8g8b8_format_list[i].shouldPass)
ok(hr == D3D_OK, "format %d %d didn't pass with hr=%#08x\n", x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat, hr);
else
ok(hr != D3D_OK, "format %d %d didn't pass while it was expected to\n", x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat);
}
}
if(d3d9) IDirect3D9_Release(d3d9);
}
START_TEST(device)
{
HMODULE d3d9_handle = LoadLibraryA( "d3d9.dll" );
......@@ -1880,6 +1999,7 @@ START_TEST(device)
ok(pDirect3DCreate9 != NULL, "Failed to get address of Direct3DCreate9\n");
if (pDirect3DCreate9)
{
test_display_formats();
test_display_modes();
test_swapchain();
test_refcount();
......
......@@ -140,6 +140,8 @@ static const struct {
static int numAdapters = 0;
static struct WineD3DAdapter Adapters[1];
static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat);
/* lookup tables */
int minLookup[MAX_LOOKUPS];
int maxLookup[MAX_LOOKUPS];
......@@ -1710,19 +1712,17 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, U
return WINED3DERR_NOTAVAILABLE;
}
static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
IWineD3DImpl *This = (IWineD3DImpl *)iface;
int nCfgs = 0;
WineD3D_PixelFormat *cfgs;
int it;
HRESULT hr = WINED3DERR_NOTAVAILABLE;
UINT nmodes;
TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
This,
Adapter,
CheckType, debug_d3ddevicetype(CheckType),
DeviceType, debug_d3ddevicetype(DeviceType),
DisplayFormat, debug_d3dformat(DisplayFormat),
BackBufferFormat, debug_d3dformat(BackBufferFormat),
Windowed);
......@@ -1732,21 +1732,66 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter
return WINED3DERR_INVALIDCALL;
}
cfgs = Adapters[Adapter].cfgs;
nCfgs = Adapters[Adapter].nCfgs;
for (it = 0; it < nCfgs; ++it) {
if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
hr = WINED3D_OK;
TRACE_(d3d_caps)("OK\n");
break ;
}
/* The task of this function is to check whether a certain display / backbuffer format
* combination is available on the given adapter. In fullscreen mode microsoft specified
* that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
* and display format should match exactly.
* In windowed mode format conversion can occur and this depends on the driver. When format
* conversion is done, this function should nevertheless fail and applications need to use
* CheckDeviceFormatConversion.
* At the moment we assume that fullscreen and windowed have the same capabilities */
/* There are only 4 display formats */
if(!((DisplayFormat == WINED3DFMT_R5G6B5) ||
(DisplayFormat == WINED3DFMT_X1R5G5B5) ||
(DisplayFormat == WINED3DFMT_X8R8G8B8) ||
(DisplayFormat == WINED3DFMT_A2R10G10B10)))
{
TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
return WINED3DERR_NOTAVAILABLE;
}
if(hr != WINED3D_OK)
ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
/* If the requested DisplayFormat is not available, don't continue */
nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
if(!nmodes) {
TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
return WINED3DERR_NOTAVAILABLE;
}
/* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
return WINED3DERR_NOTAVAILABLE;
}
/* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) {
TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
return WINED3DERR_NOTAVAILABLE;
}
/* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
return WINED3DERR_NOTAVAILABLE;
}
/* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
return WINED3DERR_NOTAVAILABLE;
}
/* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
return WINED3DERR_NOTAVAILABLE;
}
if(hr != WINED3D_OK)
TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
/* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat);
if(FAILED(hr))
TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
return hr;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment