From: Andrew D'Addesio Subject: [PATCH 5/5] ddraw: Enumerate the correct Direct3D devices in the correct order Message-Id: <1443981128-23605-5-git-send-email-andrew@fatbag.net> Date: Sun, 4 Oct 2015 12:52:08 -0500 In-Reply-To: <1443981128-23605-1-git-send-email-andrew@fatbag.net> References: <1443981128-23605-1-git-send-email-andrew@fatbag.net> Fixes 19153 --- dlls/ddraw/ddraw.c | 219 ++++++++++++++------------- dlls/ddraw/tests/d3d.c | 392 ++++++++++++++++++++++++++++--------------------- 2 files changed, 345 insertions(+), 266 deletions(-) diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index 7b5b593..91b676d 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -49,33 +49,74 @@ static const DDDEVICEIDENTIFIER2 deviceidentifier = 0 }; +#define D3D_VERSION(x) (1<<(x)) + static struct enum_device_entry { - char interface_name[100]; + unsigned int version_mask; + /* Some games (Motoracer 2 demo) have the bad idea to modify the device + * name/description strings. Let's put the strings in sufficiently sized + * arrays in static-lifetime writable memory. */ + char device_desc[100]; char device_name[100]; const GUID *device_guid; -} device_list7[] = +} device_list[] = { - /* T&L HAL device */ + /* Ramp Emulation (D3D 1&2 only) */ { - "WINE Direct3D7 Hardware Transform and Lighting acceleration using WineD3D", - "Wine D3D7 T&L HAL", - &IID_IDirect3DTnLHalDevice, + D3D_VERSION(1)|D3D_VERSION(2), + "WineD3D Ramp Software Emulation", + "Ramp Emulation", + &IID_IDirect3DRampDevice, + }, + + /* RGB Emulation (D3D 1-7) */ + { + D3D_VERSION(1)|D3D_VERSION(2)|D3D_VERSION(3)|D3D_VERSION(7), + "WineD3D RGB Software Emulation", + "RGB Emulation", + &IID_IDirect3DRGBDevice, }, - /* HAL device */ + /* Direct3D HAL (D3D 1-7) */ { - "WINE Direct3D7 Hardware acceleration using WineD3D", + D3D_VERSION(1)|D3D_VERSION(2)|D3D_VERSION(3)|D3D_VERSION(7), + "WineD3D Hardware Acceleration", "Direct3D HAL", &IID_IDirect3DHALDevice, }, - /* RGB device */ + /* MMX Emulation (D3D2 only) */ { - "WINE Direct3D7 RGB Software Emulation using WineD3D", - "Wine D3D7 RGB", - &IID_IDirect3DRGBDevice, + D3D_VERSION(2), + "WineD3D MMX Software Emulation", + "MMX Emulation", + &IID_IDirect3DMMXDevice, }, + + /* Direct3D T&L HAL (D3D7 only) */ + { + D3D_VERSION(7), + "WineD3D Hardware Transform and Lighting Acceleration", + "Direct3D T&L HAL", + &IID_IDirect3DTnLHalDevice, + }, + + /* In the future, we may wish to add the "Reference Rasterizer" and + * "Null device", which are only available in DX6-8 and must be explicitly + * enabled by the registry values: + * * EnumReference + * * EnumNullDevice, + * which are DWORD values which must be created under + * HKLM\Software\Microsoft\Direct3D\Drivers and set to any nonzero value. + * (Refer to enablerefrast.reg/disablerefrast.reg in the DX6/7 SDKs and + * KB249579 for more information.) + * + * DirectX 9.0 and higher appear to no longer recognize these settings, + * so apparently these devices were removed starting with DX9. + * + * Some games (AvP, Motoracer 2) break if these devices are enumerated. + */ }; static void STDMETHODCALLTYPE ddraw_null_wined3d_object_destroyed(void *parent) {} @@ -1369,15 +1410,6 @@ HRESULT ddraw_get_d3dcaps(const struct ddraw *ddraw, D3DDEVICEDESC7 *caps) D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_MIRROR | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_INDEPENDENTUV); - if (!(caps->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. */ - caps->dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL; - } - /* Fill the missing members, and do some fixup */ caps->dpcLineCaps.dwSize = sizeof(caps->dpcLineCaps); caps->dpcLineCaps.dwTextureBlendCaps = D3DPTBLENDCAPS_ADD @@ -3551,8 +3583,7 @@ static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface, IDirectDrawSur /***************************************************************************** * IDirect3D7::EnumDevices * - * The EnumDevices method for IDirect3D7. It enumerates all supported - * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated. + * The EnumDevices method for IDirect3D7. It enumerates all D3D7 devices. * * Params: * callback: Function to call for each enumerated device @@ -3582,12 +3613,15 @@ static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBA return hr; } - for (i = 0; i < sizeof(device_list7)/sizeof(device_list7[0]); i++) + for (i = 0; i < sizeof(device_list)/sizeof(device_list[0]); i++) { HRESULT ret; - device_desc7.deviceGUID = *device_list7[i].device_guid; - ret = callback(device_list7[i].interface_name, device_list7[i].device_name, &device_desc7, context); + if (!(device_list[i].version_mask & D3D_VERSION(7))) + continue; + + device_desc7.deviceGUID = *device_list[i].device_guid; + ret = callback(device_list[i].device_desc, device_list[i].device_name, &device_desc7, context); if (ret != DDENUMRET_OK) { TRACE("Application cancelled the enumeration.\n"); @@ -3603,11 +3637,21 @@ static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBA return D3D_OK; } +static void clear_device_desc(D3DDEVICEDESC *device_desc) +{ + memset(device_desc, 0, sizeof(*device_desc)); + device_desc->dwSize = sizeof(*device_desc); + device_desc->dtcTransformCaps.dwSize = sizeof(device_desc->dtcTransformCaps); + device_desc->dlcLightingCaps.dwSize = sizeof(device_desc->dlcLightingCaps); + device_desc->dpcLineCaps.dwSize = sizeof(device_desc->dpcLineCaps); + device_desc->dpcTriCaps.dwSize = sizeof(device_desc->dpcTriCaps); +} + /***************************************************************************** * IDirect3D3::EnumDevices * - * Enumerates all supported Direct3DDevice interfaces. This is the - * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own. + * Enumerates all Direct3DDevice interfaces. This is the implementation for + * Direct3D 1 to Direct3D 3; Version 7 has its own. * * Version 1, 2 and 3 * @@ -3622,18 +3666,12 @@ static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBA *****************************************************************************/ static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context) { - static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL"; - struct ddraw *ddraw = impl_from_IDirect3D3(iface); - D3DDEVICEDESC device_desc1, hal_desc, hel_desc; + DWORD desc_size; + D3DDEVICEDESC device_desc1, empty_desc1, hal_desc, hel_desc; D3DDEVICEDESC7 device_desc7; HRESULT hr; - - /* Some games (Motoracer 2 demo) have the bad idea to modify the device - * name string. Let's put the string in a sufficiently sized array in - * writable memory. */ - char device_name[50]; - strcpy(device_name,"Direct3D HEL"); + size_t i; TRACE("iface %p, callback %p, context %p.\n", iface, callback, context); @@ -3642,52 +3680,58 @@ static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBA wined3d_mutex_lock(); + switch (ddraw->d3dversion) + { + case 1: desc_size = D3D1_DESC_SIZE; break; + case 2: desc_size = D3D2_DESC_SIZE; break; + default: desc_size = D3D3_DESC_SIZE; break; + } + if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7))) { wined3d_mutex_unlock(); return hr; } + ddraw_d3dcaps1_from_7(&device_desc1, &device_desc7); + device_desc1.dwSize = desc_size; - /* Do I have to enumerate the reference id? Note from old d3d7: - * "It seems that enumerating the reference IID on Direct3D 1 games - * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1 - * - * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers, - * EnumReference which enables / disables enumerating the reference - * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The - * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk - * demo directory suggest this. - * - * 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 apart 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 (ddraw->d3dversion != 1) - { - static CHAR reference_description[] = "RGB Direct3D emulation"; - - TRACE("Enumerating WineD3D D3DDevice interface.\n"); - hal_desc = device_desc1; - hel_desc = device_desc1; - /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */ - hal_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 - | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); - hal_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 - | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); - /* RGB, RAMP and MMX devices have a HAL dcmColorModel of 0 */ - hal_desc.dcmColorModel = 0; - /* RGB, RAMP and MMX devices cannot report HAL hardware flags */ - hal_desc.dwFlags = 0; - - hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description, - device_name, &hal_desc, &hel_desc, context); - if (hr != D3DENUMRET_OK) + clear_device_desc(&empty_desc1); + empty_desc1.dwSize = desc_size; + + for (i = 0; i < sizeof(device_list)/sizeof(device_list[0]); i++) + { + if (!(device_list[i].version_mask & D3D_VERSION(ddraw->d3dversion))) + continue; + + if (IsEqualGUID(&IID_IDirect3DHALDevice, device_list[i].device_guid)) + { + hal_desc = device_desc1; + + /* The HAL device's hel_desc is almost empty -- but not completely */ + hel_desc = empty_desc1; + hel_desc.dwFlags = D3DDD_COLORMODEL | D3DDD_DEVCAPS | D3DDD_TRANSFORMCAPS + | D3DDD_LIGHTINGCAPS | D3DDD_BCLIPPING; + hel_desc.dcmColorModel = 0; + hel_desc.dwDevCaps = D3DDEVCAPS_FLOATTLVERTEX; + hel_desc.dtcTransformCaps.dwCaps = hal_desc.dtcTransformCaps.dwCaps; + hel_desc.dlcLightingCaps = hal_desc.dlcLightingCaps; + hel_desc.bClipping = hal_desc.bClipping; + hel_desc.dwMaxVertexCount = hal_desc.dwMaxVertexCount; + } + else + { + hal_desc = empty_desc1; + + hel_desc = device_desc1; + /* Ramp device supports grayscale only */ + if (IsEqualGUID(&IID_IDirect3DRampDevice, device_list[i].device_guid)) + hel_desc.dcmColorModel = D3DCOLOR_MONO; + } + + hr = callback((GUID *)device_list[i].device_guid, device_list[i].device_desc, + device_list[i].device_name, &hal_desc, &hel_desc, context); + if (hr != DDENUMRET_OK) { TRACE("Application cancelled the enumeration.\n"); wined3d_mutex_unlock(); @@ -3695,29 +3739,6 @@ static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBA } } - strcpy(device_name,"Direct3D HAL"); - - TRACE("Enumerating HAL Direct3D device.\n"); - hal_desc = device_desc1; - hel_desc = device_desc1; - - /* The hal device does not have the pow2 flag set in hel, but in hal. */ - hel_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 - | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); - hel_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2 - | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); - /* HAL devices have a HEL dcmColorModel of 0 */ - hel_desc.dcmColorModel = 0; - - hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description, - device_name, &hal_desc, &hel_desc, context); - if (hr != D3DENUMRET_OK) - { - TRACE("Application cancelled the enumeration.\n"); - wined3d_mutex_unlock(); - return D3D_OK; - } - TRACE("End of enumeration.\n"); wined3d_mutex_unlock(); diff --git a/dlls/ddraw/tests/d3d.c b/dlls/ddraw/tests/d3d.c index 392c13f..f4de5dd 100644 --- a/dlls/ddraw/tests/d3d.c +++ b/dlls/ddraw/tests/d3d.c @@ -70,13 +70,35 @@ enum { D3D3_DESC_SIZE = sizeof(D3DDEVICEDESC) /* 252 */ }; +enum { + device_ramp, + device_rgb, + device_hal, + device_mmx, + device_ref, + device_null, + device_tnlhal, + device_count +}; + +static const struct { + const char *device_name; + const GUID *device_guid; +} device_list[device_count] = { + {"Ramp Emulation", &IID_IDirect3DRampDevice}, + {"RGB Emulation", &IID_IDirect3DRGBDevice}, + {"Direct3D HAL", &IID_IDirect3DHALDevice}, + {"MMX Emulation", &IID_IDirect3DMMXDevice}, + {"Reference Rasterizer", &IID_IDirect3DRefDevice}, + {"Null device", &IID_IDirect3DNullDevice}, + {"Direct3D T&L HAL", &IID_IDirect3DTnLHalDevice}, +}; + typedef struct { - int total; - int rgb; - int hal; - int tnlhal; - int unk; -} D3D7ETest; + int d3dver; + int prev_device; + BOOL enumerated[device_count]; +} D3DETest; typedef struct { HRESULT desired_ret; @@ -542,147 +564,183 @@ static void LimitTest(void) IDirectDrawSurface7_Release(pTexture); } -static HRESULT WINAPI enumDevicesCallback(GUID *Guid, char *DeviceDescription, - char *DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, void *ctx) +static int identify_device(GUID *Guid) { - UINT ver = *((UINT *) ctx); - if(IsEqualGUID(&IID_IDirect3DRGBDevice, Guid)) + int i; + for (i = 0; i < device_count; i++) { - 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); + if (IsEqualGUID(device_list[i].device_guid, Guid)) + return i; + } + return -1; +} + +static void require_device(D3DETest *ctx, int device) +{ + ok(ctx->enumerated[device], "No D3D%d %s device enumerated\n", + ctx->d3dver, device_list[device].device_name); +} - ok(hal->dcmColorModel == 0, "RGB Device %u hal caps has colormodel %u\n", ver, hal->dcmColorModel); - ok(hel->dcmColorModel == D3DCOLOR_RGB, "RGB Device %u hel caps has colormodel %u\n", ver, hel->dcmColorModel); +static void prohibit_device(D3DETest *ctx, int device) +{ + ok(!ctx->enumerated[device], "D3D%d %s device was enumerated\n", + ctx->d3dver, device_list[device].device_name); +} - ok(hal->dwFlags == 0, "RGB Device %u hal caps has hardware flags %x\n", ver, hal->dwFlags); - ok(hel->dwFlags != 0, "RGB Device %u hel caps has hardware flags %x\n", ver, hel->dwFlags); +static void check_enumerated_devices(D3DETest *ctx) +{ + int ver = ctx->d3dver; + + require_device(ctx, device_rgb); + + if (ver == 1) + { + require_device(ctx, device_ramp); + prohibit_device(ctx, device_mmx); + prohibit_device(ctx, device_tnlhal); } - else if(IsEqualGUID(&IID_IDirect3DHALDevice, Guid)) + else if (ver == 2) { - trace("HAL Device %d\n", ver); - ok(hal->dcmColorModel == D3DCOLOR_RGB, "HAL Device %u hal caps has colormodel %u\n", ver, hel->dcmColorModel); - ok(hel->dcmColorModel == 0, "HAL Device %u hel caps has colormodel %u\n", ver, hel->dcmColorModel); - - ok(hal->dwFlags != 0, "HAL Device %u hal caps has hardware flags %x\n", ver, hal->dwFlags); - ok(hel->dwFlags != 0, "HAL Device %u hel caps has hardware flags %x\n", ver, hel->dwFlags); + require_device(ctx, device_ramp); + require_device(ctx, device_mmx); + prohibit_device(ctx, device_tnlhal); } - else if(IsEqualGUID(&IID_IDirect3DRefDevice, Guid)) + else if (ver == 3) { - 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); + prohibit_device(ctx, device_ramp); + prohibit_device(ctx, device_mmx); + prohibit_device(ctx, device_tnlhal); } - else if(IsEqualGUID(&IID_IDirect3DRampDevice, Guid)) + else if (ver == 7) { - 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); - - ok(hal->dcmColorModel == 0, "Ramp Device %u hal caps has colormodel %u\n", ver, hal->dcmColorModel); - ok(hel->dcmColorModel == D3DCOLOR_MONO, "Ramp Device %u hel caps has colormodel %u\n", - ver, hel->dcmColorModel); + prohibit_device(ctx, device_ramp); + prohibit_device(ctx, device_mmx); - ok(hal->dwFlags == 0, "Ramp Device %u hal caps has hardware flags %x\n", ver, hal->dwFlags); - ok(hel->dwFlags != 0, "Ramp Device %u hel caps has hardware flags %x\n", ver, hel->dwFlags); + /* A couple of games (Delta Force LW, C&C TFD) require the T&L HAL device + * to only be enumerated together with the non-T&L HAL device. */ + ok(!ctx->enumerated[device_tnlhal] || ctx->enumerated[device_hal], + "D3D%d T&L HAL device enumerated without non-T&L HAL device\n", ver); } - else if(IsEqualGUID(&IID_IDirect3DMMXDevice, Guid)) +} + +static HRESULT WINAPI enumDevicesCallback(GUID *Guid, char *DeviceDescription, + char *DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, void *Context) +{ + D3DETest *ctx = Context; + int ver = ctx->d3dver; + int device = identify_device(Guid); + DWORD expected_desc_size; + + trace("D3D%d %s\n", ver, DeviceName); + + switch (ver) { - 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); + case 1: expected_desc_size = D3D1_DESC_SIZE; break; + case 2: expected_desc_size = D3D2_DESC_SIZE; break; + default: expected_desc_size = D3D3_DESC_SIZE; break; + } - ok(hal->dcmColorModel == 0, "MMX Device %u hal caps has colormodel %u\n", ver, hal->dcmColorModel); - ok(hel->dcmColorModel == D3DCOLOR_RGB, "MMX Device %u hel caps has colormodel %u\n", ver, hel->dcmColorModel); + ok(hal->dwSize == expected_desc_size, + "D3D%d %s hal_desc has dwSize %u\n", ver, DeviceName, hal->dwSize); + ok(hel->dwSize == expected_desc_size, + "D3D%d %s hel_desc has dwSize %u\n", ver, DeviceName, hel->dwSize); - ok(hal->dwFlags == 0, "MMX Device %u hal caps has hardware flags %x\n", ver, hal->dwFlags); - ok(hel->dwFlags != 0, "MMX Device %u hel caps has hardware flags %x\n", ver, hel->dwFlags); + if (device >= 0) + { + /* Many games (DD Goin Quackers, Sims Online) search for the device + * by name, not by GUID. So ensure the device has the correct name. */ + const char *expected_name = device_list[device].device_name; + ok(!strcmp(DeviceName, expected_name), + "D3D%d %s has name \"%s\"\n", ver, expected_name, DeviceName); + + ok(device > ctx->prev_device, "D3D%d %s enumerated after %s\n", ver, + expected_name, device_list[ctx->prev_device].device_name); + ctx->prev_device = device; + ctx->enumerated[device] = 1; } 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"); + ok(0, "Unrecognized D3D%d device enumerated: desc=\"%s\", name=\"%s\"\n", + ver, DeviceDescription, DeviceName); } + + if (device == device_hal || device == device_tnlhal) + { + /* matching description */ + ok(hal->dwFlags != 0, + "D3D%d %s hal_desc has hardware flags %x\n", ver, DeviceName, hal->dwFlags); + ok(hal->dcmColorModel == D3DCOLOR_RGB, + "D3D%d %s hal_desc has colormodel %u\n", ver, DeviceName, hal->dcmColorModel); + /* Rollcage requires this dwTextureCaps flag on the matching description */ + ok(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "D3D%d %s hal_desc line caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver, DeviceName); + ok(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "D3D%d %s hal_desc tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver, DeviceName); + + /* non-matching description (should be almost empty -- but not completely) */ + ok(hel->dwFlags != 0, + "D3D%d %s hel_desc has hardware flags %x\n", ver, DeviceName, hel->dwFlags); + ok(hel->dcmColorModel == 0, + "D3D%d %s hel_desc has colormodel %u\n", ver, DeviceName, hel->dcmColorModel); + ok(hel->dpcLineCaps.dwTextureCaps == 0, + "D3D%d %s hel_desc has line caps %x\n", ver, DeviceName, hel->dpcLineCaps.dwTextureCaps); + ok(hel->dpcTriCaps.dwTextureCaps == 0, + "D3D%d %s hel_desc has tri caps %x\n", ver, DeviceName, hel->dpcTriCaps.dwTextureCaps); + } + else + { + /* matching description */ + ok(hel->dwFlags != 0, + "D3D%d %s hel_desc has hardware flags %x\n", ver, DeviceName, hel->dwFlags); + ok(hel->dcmColorModel == (device == device_ramp ? D3DCOLOR_MONO : D3DCOLOR_RGB), + "D3D%d %s hel_desc has colormodel %u\n", ver, DeviceName, hel->dcmColorModel); + /* Rollcage requires this dwTextureCaps flag on the matching description */ + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "D3D%d %s hel_desc line caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver, DeviceName); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "D3D%d %s hel_desc tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver, DeviceName); + + /* non-matching description (should be empty) */ + ok(hal->dwFlags == 0, + "D3D%d %s hal_desc has hardware flags %x\n", ver, DeviceName, hal->dwFlags); + ok(hal->dcmColorModel == 0, + "D3D%d %s hal_desc has colormodel %u\n", ver, DeviceName, hal->dcmColorModel); + ok(hal->dpcLineCaps.dwTextureCaps == 0, + "D3D%d %s hal_desc has line caps %x\n", ver, DeviceName, hal->dpcLineCaps.dwTextureCaps); + ok(hal->dpcTriCaps.dwTextureCaps == 0, + "D3D%d %s hal_desc has tri caps %x\n", ver, DeviceName, hal->dpcTriCaps.dwTextureCaps); + } + return DDENUMRET_OK; } static HRESULT WINAPI enumDevicesCallbackTest7(char *DeviceDescription, char *DeviceName, D3DDEVICEDESC7 *lpdd7, void *Context) { - D3D7ETest *d3d7et = Context; - if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DRGBDevice)) - d3d7et->rgb++; - else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DHALDevice)) - d3d7et->hal++; - else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DTnLHalDevice)) - d3d7et->tnlhal++; - else - d3d7et->unk++; + D3DETest *ctx = Context; + int ver = ctx->d3dver; + int device = identify_device(&lpdd7->deviceGUID); - d3d7et->total++; + trace("D3D%d %s\n", ver, DeviceName); + + if (device >= 0) + { + /* Many games (DD Goin Quackers, Sims Online) search for the device + * by name, not by GUID. So ensure the device has the correct name. */ + const char *expected_name = device_list[device].device_name; + ok(!strcmp(DeviceName, expected_name), + "D3D%d %s has name \"%s\"\n", ver, expected_name, DeviceName); + + ok(device > ctx->prev_device, "D3D%d %s enumerated after %s\n", ver, + expected_name, device_list[ctx->prev_device].device_name); + ctx->prev_device = device; + ctx->enumerated[device] = 1; + } + else + { + ok(0, "Unrecognized D3D%d device enumerated: desc=\"%s\", name=\"%s\"\n", + ver, DeviceDescription, DeviceName); + } return DDENUMRET_OK; } @@ -717,29 +775,21 @@ static HRESULT WINAPI enumDevicesLifetimeTest7(char *DeviceDescription, char *De return DDENUMRET_OK; } -/* Check the deviceGUID of devices enumerated by - IDirect3D7_EnumDevices. */ static void D3D7EnumTest(void) { HRESULT hr; - D3D7ETest d3d7et; + D3DETest d3det; D3D7ECancelTest d3d7_cancel_test; hr = IDirect3D7_EnumDevices(lpD3D, NULL, NULL); - ok(hr == DDERR_INVALIDPARAMS, "IDirect3D7_EnumDevices returned 0x%08x\n", hr); + ok(hr == DDERR_INVALIDPARAMS, "IDirect3D7_EnumDevices returned 0x%08x for null input\n", hr); - memset(&d3d7et, 0, sizeof(d3d7et)); - hr = IDirect3D7_EnumDevices(lpD3D, enumDevicesCallbackTest7, &d3d7et); + d3det.d3dver = 7; + d3det.prev_device = -1; + memset(&d3det.enumerated, 0, sizeof(d3det.enumerated)); + hr = IDirect3D7_EnumDevices(lpD3D, enumDevicesCallbackTest7, &d3det); ok(hr == D3D_OK, "IDirect3D7_EnumDevices returned 0x%08x\n", hr); - - /* A couple of games (Delta Force LW and TFD) rely on this behaviour */ - ok(d3d7et.tnlhal < d3d7et.total, "TnLHal device enumerated as only device.\n"); - - /* We make two additional assumptions. */ - ok(d3d7et.rgb, "No RGB Device enumerated.\n"); - - if(d3d7et.tnlhal) - ok(d3d7et.hal, "TnLHal device enumerated, but no Hal device found.\n"); + check_enumerated_devices(&d3det); d3d7_cancel_test.desired_ret = DDENUMRET_CANCEL; d3d7_cancel_test.total = 0; @@ -835,41 +885,52 @@ static void D3D7EnumLifetimeTest(void) } } -static void CapsTest(void) +static void D3D1EnumTest(void) { - IDirect3D3 *d3d3; - IDirect3D3 *d3d2; - IDirectDraw *dd1; + D3DETest d3det; 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); + hr = IDirect3D_EnumDevices(Direct3D1, NULL, NULL); + ok(hr == DDERR_INVALIDPARAMS, "IDirect3D_EnumDevices returned 0x%08x for null input\n", hr); - hr = IDirect3D3_EnumDevices(d3d3, NULL, NULL); - ok(hr == DDERR_INVALIDPARAMS, "IDirect3D3_EnumDevices returned 0x%08x\n", hr); + d3det.d3dver = 1; + d3det.prev_device = -1; + memset(&d3det.enumerated, 0, sizeof(d3det.enumerated)); + hr = IDirect3D_EnumDevices(Direct3D1, enumDevicesCallback, &d3det); + ok(hr == DD_OK, "IDirect3D_EnumDevices returned %08x\n", hr); + check_enumerated_devices(&d3det); +} - ver = 3; - IDirect3D3_EnumDevices(d3d3, enumDevicesCallback, &ver); +static void D3D2EnumTest(struct d3d2_test_context *context) +{ + D3DETest d3det; + HRESULT hr; - IDirect3D3_Release(d3d3); - IDirectDraw_Release(dd1); + hr = IDirect3D2_EnumDevices(context->d3d, NULL, NULL); + ok(hr == DDERR_INVALIDPARAMS, "IDirect3D2_EnumDevices returned 0x%08x for null input\n", hr); - 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); + d3det.d3dver = 2; + d3det.prev_device = -1; + memset(&d3det.enumerated, 0, sizeof(d3det.enumerated)); + hr = IDirect3D2_EnumDevices(context->d3d, enumDevicesCallback, &d3det); + ok(hr == DD_OK, "IDirect3D2_EnumDevices returned %08x\n", hr); + check_enumerated_devices(&d3det); +} - hr = IDirect3D2_EnumDevices(d3d2, NULL, NULL); - ok(hr == DDERR_INVALIDPARAMS, "IDirect3D2_EnumDevices returned 0x%08x\n", hr); +static void D3D3EnumTest(struct d3d3_test_context *context) +{ + D3DETest d3det; + HRESULT hr; - ver = 2; - IDirect3D2_EnumDevices(d3d2, enumDevicesCallback, &ver); + hr = IDirect3D3_EnumDevices(context->d3d, NULL, NULL); + ok(hr == DDERR_INVALIDPARAMS, "IDirect3D3_EnumDevices returned 0x%08x for null input\n", hr); - IDirect3D2_Release(d3d2); - IDirectDraw_Release(dd1); + d3det.d3dver = 3; + d3det.prev_device = -1; + memset(&d3det.enumerated, 0, sizeof(d3det.enumerated)); + hr = IDirect3D3_EnumDevices(context->d3d, enumDevicesCallback, &d3det); + ok(hr == DD_OK, "IDirect3D3_EnumDevices returned %08x\n", hr); + check_enumerated_devices(&d3det); } struct v_in { @@ -4103,21 +4164,18 @@ error: return FALSE; } -static void d3d3_nop_test(const struct d3d3_test_context *context) -{ -} - START_TEST(d3d) { struct d3d3_test_context d3d3_context; void (* const d3d3_tests[])(const struct d3d3_test_context *) = { - d3d3_nop_test /* please remove once the first real d3d3 test is added */ + D3D3EnumTest }; struct d3d2_test_context d3d2_context; void (* const d3d2_tests[])(const struct d3d2_test_context *) = { + D3D2EnumTest, test_get_caps2 }; @@ -4136,7 +4194,6 @@ START_TEST(d3d) D3D7EnumLifetimeTest(); SetMaterialTest(); ComputeSphereVisibility(); - CapsTest(); VertexBufferDescTest(); D3D7_OldRenderStateTest(); DeviceLoadTest(); @@ -4177,6 +4234,7 @@ START_TEST(d3d) Direct3D1Test(); TextureLoadTest(); ViewportTest(); + D3D1EnumTest(); FindDevice(); BackBuffer3DCreateSurfaceTest(); BackBuffer3DAttachmentTest(); -- 2.4.3