From d9fef10b71b9add27cfaeffa6d7e3ab42342bba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Wed, 9 May 2007 11:49:27 +0200 Subject: [PATCH] ddraw: Some caps fixes. Cards at DirectX7 times did not support non power of 2 textures, and some games check the capatiblity flags incorrectly. Rollcage expects the D3DPTEXTURECAPS_POW2 (limitation) flag set and fails with the reference rasterizer which support NP2 textures and doesn't have the cap set. --- dlls/ddraw/direct3d.c | 25 +++++-- dlls/ddraw/tests/d3d.c | 155 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 174 insertions(+), 6 deletions(-) diff --git a/dlls/ddraw/direct3d.c b/dlls/ddraw/direct3d.c index 0ccb2c30c40..5dee99a5f67 100644 --- a/dlls/ddraw/direct3d.c +++ b/dlls/ddraw/direct3d.c @@ -312,16 +312,24 @@ IDirect3DImpl_3_EnumDevices(IDirect3D3 *iface, * * Some games(GTA 2) seem to use the second enumerated device, so I have to enumerate * at least 2 devices. So enumerate the reference device to have 2 devices. + * + * Other games(Rollcage) tell emulation and hal device appart by certain flags. + * Rollcage expects D3DPTEXTURECAPS_POW2 to be set(yeah, it is a limitation flag), + * and it refuses all devices that have the perspective flag set. This way it refuses + * the emulation device, and HAL devices never have POW2 unset in d3d7 on windows. */ if(This->d3dversion != 1) { - static CHAR reference_description[] = "Reference Direct3D ID"; + static CHAR reference_description[] = "RGB Direct3D emulation"; TRACE("(%p) Enumerating WineD3D D3DDevice interface\n", This); d1 = dref; d2 = dref; - hr = Callback( (LPIID) &IID_IDirect3DRefDevice, reference_description, device_name, &d1, &d2, Context); + /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps */ + d1.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); + d1.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); + hr = Callback( (LPIID) &IID_IDirect3DRGBDevice, reference_description, device_name, &d1, &d2, Context); if(hr != D3DENUMRET_OK) { TRACE("Application cancelled the enumeration\n"); @@ -329,10 +337,13 @@ IDirect3DImpl_3_EnumDevices(IDirect3D3 *iface, } } - TRACE("(%p) Enumerating WineD3D D3DDevice interface\n", This); + TRACE("(%p) Enumerating HAL Direct3D device\n", This); d1 = dref; d2 = dref; - hr = Callback( (LPIID) &IID_D3DDEVICE_WineD3D, wined3d_description, device_name, &d1, &d2, Context); + /* The hal device does not have the pow2 flag set in hel, but in hal */ + d2.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); + d2.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); + hr = Callback( (LPIID) &IID_IDirect3DHALDevice, wined3d_description, device_name, &d1, &d2, Context); if(hr != D3DENUMRET_OK) { TRACE("Application cancelled the enumeration\n"); @@ -1304,6 +1315,12 @@ IDirect3DImpl_GetCaps(IWineD3D *WineD3D, hr = IWineD3D_GetDeviceCaps(WineD3D, 0, WINED3DDEVTYPE_HAL, &WCaps); if(hr != D3D_OK) return hr; + if(!(Desc7->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)) { + /* DirectX7 always has the np2 flag set, no matter what the card supports. Some old games(rollcage) + * check the caps incorrectly. If wined3d supports nonpow2 textures it also has np2 conditional support + */ + Desc7->dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL; + } /* Fill the missing members, and do some fixup */ Desc7->dpcLineCaps.dwSize = sizeof(Desc7->dpcLineCaps); Desc7->dpcLineCaps.dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_MODULATEMASK | diff --git a/dlls/ddraw/tests/d3d.c b/dlls/ddraw/tests/d3d.c index 299fae8a478..bca7d815e6e 100644 --- a/dlls/ddraw/tests/d3d.c +++ b/dlls/ddraw/tests/d3d.c @@ -90,8 +90,18 @@ static BOOL CreateDirect3D(void) &lpD3DDevice); ok(rc==D3D_OK || rc==DDERR_NOPALETTEATTACHED || rc==E_OUTOFMEMORY, "CreateDevice returned: %x\n", rc); if (!lpD3DDevice) { - trace("IDirect3D7::CreateDevice() failed with an error %x\n", rc); - return FALSE; + trace("IDirect3D7::CreateDevice() for a TnL Hal device failed with an error %x, trying HAL\n", rc); + rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DHALDevice, lpDDS, + &lpD3DDevice); + if (!lpD3DDevice) { + trace("IDirect3D7::CreateDevice() for a HAL device failed with an error %x, trying RGB\n", rc); + rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DRGBDevice, lpDDS, + &lpD3DDevice); + if (!lpD3DDevice) { + trace("IDirect3D7::CreateDevice() for a RGB device failed with an error %x, giving up\n", rc); + return FALSE; + } + } } return TRUE; @@ -605,6 +615,146 @@ static void LimitTest(void) IDirectDrawSurface7_Release(pTexture); } +static HRESULT WINAPI enumDevicesCallback(GUID *Guid,LPSTR DeviceDescription,LPSTR DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, VOID *ctx) +{ + UINT ver = *((UINT *) ctx); + if(IsEqualGUID(&IID_IDirect3DRGBDevice, Guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "RGB Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "RGB Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "RGB Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "RGB Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "RGB Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + } + else if(IsEqualGUID(&IID_IDirect3DHALDevice, Guid)) + { + /* pow2 is hardware dependent */ + + ok(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "HAL Device %d hal line caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + ok(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "HAL Device %d hal tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + ok((hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "HAL Device %d hel line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + ok((hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "HAL Device %d hel tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + } + else if(IsEqualGUID(&IID_IDirect3DRefDevice, Guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "REF Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "REF Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "REF Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "REF Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "REF Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + } + else if(IsEqualGUID(&IID_IDirect3DRampDevice, Guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "Ramp Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "Ramp Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "Ramp Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + } + else if(IsEqualGUID(&IID_IDirect3DMMXDevice, Guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "MMX Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "MMX Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "MMX Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "MMX Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "MMX Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); + } + else + { + ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", DeviceDescription, DeviceName); + if(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal line has pow2 set\n"); + else trace("hal line does NOT have pow2 set\n"); + if(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal tri has pow2 set\n"); + else trace("hal tri does NOT have pow2 set\n"); + if(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel line has pow2 set\n"); + else trace("hel line does NOT have pow2 set\n"); + if(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel tri has pow2 set\n"); + else trace("hel tri does NOT have pow2 set\n"); + } + return DDENUMRET_OK; +} + +static void CapsTest(void) +{ + IDirect3D3 *d3d3; + IDirect3D3 *d3d2; + IDirectDraw *dd1; + HRESULT hr; + UINT ver; + + hr = DirectDrawCreate(NULL, &dd1, NULL); + ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr); + hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D3, (void **) &d3d3); + ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr); + ver = 3; + IDirect3D3_EnumDevices(d3d3, enumDevicesCallback, &ver); + + IDirect3D3_Release(d3d3); + IDirectDraw_Release(dd1); + + hr = DirectDrawCreate(NULL, &dd1, NULL); + ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr); + hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D2, (void **) &d3d2); + ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr); + ver = 2; + IDirect3D2_EnumDevices(d3d2, enumDevicesCallback, &ver); + + IDirect3D2_Release(d3d2); + IDirectDraw_Release(dd1); +} + START_TEST(d3d) { init_function_pointers(); @@ -622,5 +772,6 @@ START_TEST(d3d) StateTest(); SceneTest(); LimitTest(); + CapsTest(); ReleaseDirect3D(); }