d3d: Fix adapter mode enumeration and filtering.

This commit is contained in:
Chris Robinson 2006-12-20 04:44:08 -08:00 committed by Alexandre Julliard
parent e4a6562937
commit ed21935479
4 changed files with 180 additions and 73 deletions

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2006 Vitaliy Margolen * Copyright (C) 2006 Vitaliy Margolen
* Copyright (C) 2006 Chris Robinson
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -686,6 +687,35 @@ cleanup:
if(pDevice) IDirect3D8_Release(pDevice); if(pDevice) IDirect3D8_Release(pDevice);
} }
/* Test adapter display modes */
static void test_display_modes(void)
{
UINT max_modes, i;
D3DDISPLAYMODE dmode;
HRESULT res;
IDirect3D8 *pD3d;
pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
if(!pD3d) return;
max_modes = IDirect3D8_GetAdapterModeCount(pD3d, D3DADAPTER_DEFAULT);
ok(max_modes > 0, "GetAdapterModeCount(D3DADAPTER_DEFAULT) returned 0!\n");
for(i=0; i<max_modes;i++) {
res = IDirect3D8_EnumAdapterModes(pD3d, D3DADAPTER_DEFAULT, i, &dmode);
ok(res==D3D_OK, "EnumAdapterModes returned %s for mode %u!\n", DXGetErrorString8(res), i);
if(res != D3D_OK)
continue;
ok(dmode.Format==D3DFMT_X8R8G8B8 || dmode.Format==D3DFMT_R5G6B5,
"Unexpected display mode returned for mode %u: %#x\n", i , dmode.Format);
}
IDirect3D8_Release(pD3d);
}
START_TEST(device) START_TEST(device)
{ {
HMODULE d3d8_handle = LoadLibraryA( "d3d8.dll" ); HMODULE d3d8_handle = LoadLibraryA( "d3d8.dll" );
@ -693,6 +723,7 @@ START_TEST(device)
pDirect3DCreate8 = (void *)GetProcAddress( d3d8_handle, "Direct3DCreate8" ); pDirect3DCreate8 = (void *)GetProcAddress( d3d8_handle, "Direct3DCreate8" );
if (pDirect3DCreate8) if (pDirect3DCreate8)
{ {
test_display_modes();
test_swapchain(); test_swapchain();
test_refcount(); test_refcount();
test_mipmap_levels(); test_mipmap_levels();

View File

@ -103,6 +103,10 @@ static UINT WINAPI IDirect3D9Impl_GetAdapterModeCount(LPDIRECT3D9 iface, UINT Ad
static HRESULT WINAPI IDirect3D9Impl_EnumAdapterModes(LPDIRECT3D9 iface, UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) { static HRESULT WINAPI IDirect3D9Impl_EnumAdapterModes(LPDIRECT3D9 iface, UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) {
IDirect3D9Impl *This = (IDirect3D9Impl *)iface; IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
/* We can't pass this to WineD3D, otherwise it'll think it came from D3D8.
It's supposed to fail anyway, so no harm returning failure. */
if(Format == D3DFMT_UNKNOWN)
return D3DERR_INVALIDCALL;
return IWineD3D_EnumAdapterModes(This->WineD3D, Adapter, Format, Mode, (WINED3DDISPLAYMODE *) pMode); return IWineD3D_EnumAdapterModes(This->WineD3D, Adapter, Format, Mode, (WINED3DDISPLAYMODE *) pMode);
} }

View File

@ -1,6 +1,7 @@
/* /*
* Copyright (C) 2006 Vitaliy Margolen * Copyright (C) 2006 Vitaliy Margolen
* Copyright (C) 2006 Stefan Dösinger(For CodeWeavers) * Copyright (C) 2006 Stefan Dösinger(For CodeWeavers)
* Copyright (C) 2006 Chris Robinson
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -838,6 +839,96 @@ cleanup:
if(pDevice) IDirect3D9_Release(pDevice); if(pDevice) IDirect3D9_Release(pDevice);
} }
/* Test adapter display modes */
static void test_display_modes(void)
{
D3DDISPLAYMODE dmode;
IDirect3D9 *pD3d;
pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
if(!pD3d) return;
#define TEST_FMT(x,r) do { \
HRESULT res = IDirect3D9_EnumAdapterModes(pD3d, 0, (x), 0, &dmode); \
ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %s)!\n", DXGetErrorString9(res)); \
} while(0)
TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_A2R10G10B10, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_W11V11U10, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_MULTI2_ARGB, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
/* Flaoting point formats */
TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
/* IEEE formats */
TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
TEST_FMT(0, D3DERR_INVALIDCALL);
IDirect3D9_Release(pD3d);
}
START_TEST(device) START_TEST(device)
{ {
HMODULE d3d9_handle = LoadLibraryA( "d3d9.dll" ); HMODULE d3d9_handle = LoadLibraryA( "d3d9.dll" );
@ -845,6 +936,7 @@ START_TEST(device)
pDirect3DCreate9 = (void *)GetProcAddress( d3d9_handle, "Direct3DCreate9" ); pDirect3DCreate9 = (void *)GetProcAddress( d3d9_handle, "Direct3DCreate9" );
if (pDirect3DCreate9) if (pDirect3DCreate9)
{ {
test_display_modes();
test_swapchain(); test_swapchain();
test_refcount(); test_refcount();
test_mipmap_levels(); test_mipmap_levels();

View File

@ -1080,31 +1080,23 @@ static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Ad
#if !defined( DEBUG_SINGLE_MODE ) #if !defined( DEBUG_SINGLE_MODE )
DEVMODEW DevModeW; DEVMODEW DevModeW;
/* Work out the current screen bpp */
HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
int bpp = GetDeviceCaps(hdc, BITSPIXEL);
DeleteDC(hdc);
while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) { while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
j++; j++;
switch (Format) switch (Format)
{ {
case WINED3DFMT_UNKNOWN: case WINED3DFMT_UNKNOWN:
i++; if (DevModeW.dmBitsPerPel == 32 ||
break; DevModeW.dmBitsPerPel == 16) i++;
case WINED3DFMT_X8R8G8B8: break;
case WINED3DFMT_A8R8G8B8: case WINED3DFMT_X8R8G8B8:
if (min(DevModeW.dmBitsPerPel, bpp) == 32) i++; if (DevModeW.dmBitsPerPel == 32) i++;
if (min(DevModeW.dmBitsPerPel, bpp) == 24) i++; break;
break; case WINED3DFMT_R5G6B5:
case WINED3DFMT_X1R5G5B5: if (DevModeW.dmBitsPerPel == 16) i++;
case WINED3DFMT_A1R5G5B5: break;
case WINED3DFMT_R5G6B5: default:
if (min(DevModeW.dmBitsPerPel, bpp) == 16) i++; /* Skip other modes as they do not match the requested format */
break; break;
default:
/* Skip other modes as they do not match the requested format */
break;
} }
} }
#else #else
@ -1132,79 +1124,67 @@ static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapte
} }
if (Adapter == 0) { /* Display */ if (Adapter == 0) { /* Display */
int bpp;
#if !defined( DEBUG_SINGLE_MODE ) #if !defined( DEBUG_SINGLE_MODE )
DEVMODEW DevModeW; DEVMODEW DevModeW;
int ModeIdx = 0; int ModeIdx = 0;
int i = 0;
int j = 0;
/* Work out the current screen bpp */ /* If we are filtering to a specific format (D3D9), then need to skip
HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); all unrelated modes, but if mode is irrelevant (D3D8), then we can
bpp = GetDeviceCaps(hdc, BITSPIXEL); just count through the ones with valid bit depths */
DeleteDC(hdc); while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
switch (Format)
/* If we are filtering to a specific format, then need to skip all unrelated {
modes, but if mode is irrelevant, then we can use the index directly */
if (Format == WINED3DFMT_UNKNOWN)
{
ModeIdx = Mode;
} else {
int i = 0;
int j = 0;
DEVMODEW DevModeWtmp;
while (i<(Mode) && EnumDisplaySettingsExW(NULL, j, &DevModeWtmp, 0)) {
j++;
switch (Format)
{
case WINED3DFMT_UNKNOWN: case WINED3DFMT_UNKNOWN:
i++; if (DevModeW.dmBitsPerPel == 32 ||
break; DevModeW.dmBitsPerPel == 16) i++;
break;
case WINED3DFMT_X8R8G8B8: case WINED3DFMT_X8R8G8B8:
case WINED3DFMT_A8R8G8B8: if (DevModeW.dmBitsPerPel == 32) i++;
if (min(DevModeWtmp.dmBitsPerPel, bpp) == 32) i++; break;
if (min(DevModeWtmp.dmBitsPerPel, bpp) == 24) i++;
break;
case WINED3DFMT_X1R5G5B5:
case WINED3DFMT_A1R5G5B5:
case WINED3DFMT_R5G6B5: case WINED3DFMT_R5G6B5:
if (min(DevModeWtmp.dmBitsPerPel, bpp) == 16) i++; if (DevModeW.dmBitsPerPel == 16) i++;
break; break;
default: default:
/* Skip other modes as they do not match requested format */ /* Modes that don't match what we support can get an early-out */
break; TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
} return WINED3DERR_INVALIDCALL;
} }
ModeIdx = j;
} }
if (i == 0) {
TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
return WINED3DERR_INVALIDCALL;
}
ModeIdx = j - 1;
/* Now get the display mode via the calculated index */ /* Now get the display mode via the calculated index */
if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
{
pMode->Width = DevModeW.dmPelsWidth; pMode->Width = DevModeW.dmPelsWidth;
pMode->Height = DevModeW.dmPelsHeight; pMode->Height = DevModeW.dmPelsHeight;
bpp = min(DevModeW.dmBitsPerPel, bpp);
pMode->RefreshRate = D3DADAPTER_DEFAULT; pMode->RefreshRate = D3DADAPTER_DEFAULT;
if (DevModeW.dmFields & DM_DISPLAYFREQUENCY) if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
{
pMode->RefreshRate = DevModeW.dmDisplayFrequency; pMode->RefreshRate = DevModeW.dmDisplayFrequency;
}
if (Format == WINED3DFMT_UNKNOWN) if (Format == WINED3DFMT_UNKNOWN)
{ {
switch (bpp) { switch (DevModeW.dmBitsPerPel)
case 8: pMode->Format = WINED3DFMT_R3G3B2; break; {
case 16: pMode->Format = WINED3DFMT_R5G6B5; break; case 16:
case 24: /* Robots and EVE Online need 24 and 32 bit as A8R8G8B8 to start */ pMode->Format = WINED3DFMT_R5G6B5;
case 32: pMode->Format = WINED3DFMT_A8R8G8B8; break; break;
default: pMode->Format = WINED3DFMT_UNKNOWN; case 32:
pMode->Format = WINED3DFMT_X8R8G8B8;
break;
default:
pMode->Format = WINED3DFMT_UNKNOWN;
ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
} }
} else { } else {
pMode->Format = Format; pMode->Format = Format;
} }
} } else {
else
{
TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode); TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
return WINED3DERR_INVALIDCALL; return WINED3DERR_INVALIDCALL;
} }
@ -1215,11 +1195,11 @@ static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapte
pMode->Width = 800; pMode->Width = 800;
pMode->Height = 600; pMode->Height = 600;
pMode->RefreshRate = D3DADAPTER_DEFAULT; pMode->RefreshRate = D3DADAPTER_DEFAULT;
pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_A8R8G8B8 : Format; pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
bpp = 32;
#endif #endif
TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height, TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format), bpp); pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
DevModeW.dmBitsPerPel);
} else { } else {
FIXME_(d3d_caps)("Adapter not primary display\n"); FIXME_(d3d_caps)("Adapter not primary display\n");