[PATCH 5/5] ddraw: Enumerate the correct Direct3D devices in the correct order

Andrew D'Addesio andrew at fatbag.net
Sun Oct 4 12:46:06 CDT 2015


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




More information about the wine-patches mailing list