[PATCH] ddraw/tests: Also test RT caps for software device.

Paul Gofman pgofman at codeweavers.com
Wed Feb 17 14:44:19 CST 2021


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
    Supersedes 199974, 199975, 199989, 199990.
    Changes:
    - squash patches for different ddraw versions into one;
    - use 'const GUID *' instead of 'REFCLSID';
    - don't change D3D_OK to DD_OK in test data;
    - fix typo ("hardware");
    - pass the device guid as parameter to test function.

 dlls/ddraw/tests/ddraw1.c |  72 +++++++++-----
 dlls/ddraw/tests/ddraw2.c |  98 ++++++++++++-------
 dlls/ddraw/tests/ddraw4.c | 170 ++++++++++++++++++++++-----------
 dlls/ddraw/tests/ddraw7.c | 191 +++++++++++++++++++++++++-------------
 4 files changed, 361 insertions(+), 170 deletions(-)

diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index d3e9fe0e1ff..96930a5f722 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -166,6 +166,11 @@ static BOOL ddraw_is_vmware(IDirectDraw *ddraw)
     return ddraw_is_vendor(ddraw, 0x15ad);
 }
 
+static BOOL is_software_device_type(const GUID *device_guid)
+{
+    return device_guid != &IID_IDirect3DHALDevice;
+}
+
 static IDirectDrawSurface *create_overlay(IDirectDraw *ddraw,
         unsigned int width, unsigned int height, DWORD format)
 {
@@ -605,7 +610,7 @@ static IDirectDraw *create_ddraw(void)
     return ddraw;
 }
 
-static IDirect3DDevice *create_device(IDirectDraw *ddraw, HWND window, DWORD coop_level)
+static IDirect3DDevice *create_device_ex(IDirectDraw *ddraw, HWND window, DWORD coop_level, const GUID *device_guid)
 {
     /* Prefer 16 bit depth buffers because Nvidia gives us an unpadded D24 buffer if we ask
      * for 24 bit and handles such buffers incorrectly in DDBLT_DEPTHFILL. AMD only supports
@@ -665,7 +670,7 @@ static IDirect3DDevice *create_device(IDirectDraw *ddraw, HWND window, DWORD coo
         if (FAILED(hr))
             continue;
 
-        if (SUCCEEDED(IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device)))
+        if (SUCCEEDED(IDirectDrawSurface_QueryInterface(surface, device_guid, (void **)&device)))
             break;
 
         IDirectDrawSurface_DeleteAttachedSurface(surface, 0, ds);
@@ -675,6 +680,11 @@ static IDirect3DDevice *create_device(IDirectDraw *ddraw, HWND window, DWORD coo
     return device;
 }
 
+static IDirect3DDevice *create_device(IDirectDraw *ddraw, HWND window, DWORD coop_level)
+{
+    return create_device_ex(ddraw, window, coop_level, &IID_IDirect3DHALDevice);
+}
+
 static IDirect3DViewport *create_viewport(IDirect3DDevice *device, UINT x, UINT y, UINT w, UINT h)
 {
     IDirect3DViewport *viewport;
@@ -4316,11 +4326,12 @@ static void test_unsupported_formats(void)
     DestroyWindow(window);
 }
 
-static void test_rt_caps(void)
+static void test_rt_caps(const GUID *device_guid)
 {
     PALETTEENTRY palette_entries[256];
     IDirectDrawPalette *palette;
     IDirect3DDevice *device;
+    BOOL software_device;
     IDirectDraw *ddraw;
     DWORD z_depth = 0;
     unsigned int i;
@@ -4486,10 +4497,12 @@ static void test_rt_caps(void)
         },
     };
 
+    software_device = is_software_device_type(device_guid);
+
     window = create_window();
     ddraw = create_ddraw();
     ok(!!ddraw, "Failed to create a ddraw object.\n");
-    if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
+    if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid)))
     {
         skip("Failed to create a 3D device, skipping test.\n");
         IDirectDraw_Release(ddraw);
@@ -4502,7 +4515,7 @@ static void test_rt_caps(void)
 
     memset(palette_entries, 0, sizeof(palette_entries));
     hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
-    ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
+    ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
 
     for (i = 0; i < ARRAY_SIZE(test_data); ++i)
     {
@@ -4527,32 +4540,41 @@ static void test_rt_caps(void)
         surface_desc.dwWidth = 640;
         surface_desc.dwHeight = 480;
         hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
-        ok(SUCCEEDED(hr) || broken(test_data[i].create_may_fail),
-                "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
-                i, test_data[i].caps_in, hr);
+        ok(hr == DD_OK || broken(test_data[i].create_may_fail),
+                "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
+
         if (FAILED(hr))
             continue;
 
         memset(&surface_desc, 0, sizeof(surface_desc));
         surface_desc.dwSize = sizeof(surface_desc);
         hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
-        ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
-        ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
-                "Test %u: Got unexpected caps %#x, expected %#x.\n",
-                i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
-
-        hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
-        ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
-                i, hr, test_data[i].create_device_hr);
+        ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
+        ok(test_data[i].caps_out == ~0u || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
+                "Got unexpected caps %#x, expected %#x, test %u, software_device %u.\n",
+                surface_desc.ddsCaps.dwCaps, test_data[i].caps_out, i, software_device);
+
+        hr = IDirectDrawSurface_QueryInterface(surface, device_guid, (void **)&device);
+        todo_wine_if(software_device && test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM)
+        ok((!software_device && hr == test_data[i].create_device_hr)
+                || (software_device && (hr == (test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM
+                ? DD_OK : test_data[i].create_device_hr))),
+                "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
         if (hr == DDERR_NOPALETTEATTACHED)
         {
             hr = IDirectDrawSurface_SetPalette(surface, palette);
-            ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
-            hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
-            if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
-                ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+            ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
+            hr = IDirectDrawSurface_QueryInterface(surface, device_guid, (void **)&device);
+            if (software_device)
+                todo_wine
+                ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n",
+                        hr, i, software_device);
+            else if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
+                ok(hr == DDERR_INVALIDPIXELFORMAT, "Got unexpected hr %#x, test %u, software_device %u.\n",
+                        hr, i, software_device);
             else
-                ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
+                ok(hr == D3DERR_SURFACENOTINVIDMEM, "Got unexpected hr %#x, test %u, software_device %u.\n",
+                        hr, i, software_device);
         }
         if (SUCCEEDED(hr))
         {
@@ -14407,6 +14429,12 @@ static void test_get_display_mode(void)
     IDirectDraw_Release(ddraw);
 }
 
+static void run_for_each_device_type(void (*test_func)(const GUID *))
+{
+    test_func(&IID_IDirect3DHALDevice);
+    test_func(&IID_IDirect3DRGBDevice);
+}
+
 START_TEST(ddraw1)
 {
     DDDEVICEIDENTIFIER identifier;
@@ -14468,7 +14496,7 @@ START_TEST(ddraw1)
     test_clear_rect_count();
     test_coop_level_activateapp();
     test_unsupported_formats();
-    test_rt_caps();
+    run_for_each_device_type(test_rt_caps);
     test_primary_caps();
     test_surface_lock();
     test_surface_discard();
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index bc915c97864..2b16b742a32 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -163,6 +163,11 @@ static BOOL ddraw_is_vmware(IDirectDraw2 *ddraw)
     return ddraw_is_vendor(ddraw, 0x15ad);
 }
 
+static BOOL is_software_device_type(const GUID *device_guid)
+{
+    return device_guid != &IID_IDirect3DHALDevice;
+}
+
 static IDirectDrawSurface *create_overlay(IDirectDraw2 *ddraw,
         unsigned int width, unsigned int height, DWORD format)
 {
@@ -435,7 +440,7 @@ static IDirectDraw2 *create_ddraw(void)
     return ddraw2;
 }
 
-static IDirect3DDevice2 *create_device(IDirectDraw2 *ddraw, HWND window, DWORD coop_level)
+static IDirect3DDevice2 *create_device_ex(IDirectDraw2 *ddraw, HWND window, DWORD coop_level, const GUID *device_guid)
 {
     /* Prefer 16 bit depth buffers because Nvidia gives us an unpadded D24 buffer if we ask
      * for 24 bit and handles such buffers incorrectly in DDBLT_DEPTHFILL. AMD only supports
@@ -503,7 +508,7 @@ static IDirect3DDevice2 *create_device(IDirectDraw2 *ddraw, HWND window, DWORD c
         if (FAILED(hr))
             continue;
 
-        if (SUCCEEDED(IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device)))
+        if (SUCCEEDED(IDirect3D2_CreateDevice(d3d, device_guid, surface, &device)))
             break;
 
         IDirectDrawSurface_DeleteAttachedSurface(surface, 0, ds);
@@ -514,6 +519,11 @@ static IDirect3DDevice2 *create_device(IDirectDraw2 *ddraw, HWND window, DWORD c
     return device;
 }
 
+static IDirect3DDevice2 *create_device(IDirectDraw2 *ddraw, HWND window, DWORD coop_level)
+{
+    return create_device_ex(ddraw, window, coop_level, &IID_IDirect3DHALDevice);
+}
+
 static IDirect3DViewport2 *create_viewport(IDirect3DDevice2 *device, UINT x, UINT y, UINT w, UINT h)
 {
     IDirect3DViewport2 *viewport;
@@ -4739,11 +4749,12 @@ static void test_unsupported_formats(void)
     DestroyWindow(window);
 }
 
-static void test_rt_caps(void)
+static void test_rt_caps(const GUID *device_guid)
 {
     PALETTEENTRY palette_entries[256];
     IDirectDrawPalette *palette;
     IDirect3DDevice2 *device;
+    BOOL software_device;
     IDirectDraw2 *ddraw;
     DWORD z_depth = 0;
     IDirect3D2 *d3d;
@@ -4952,10 +4963,12 @@ static void test_rt_caps(void)
         },
     };
 
+    software_device = is_software_device_type(device_guid);
+
     window = create_window();
     ddraw = create_ddraw();
     ok(!!ddraw, "Failed to create a ddraw object.\n");
-    if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
+    if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid)))
     {
         skip("Failed to create a 3D device, skipping test.\n");
         IDirectDraw2_Release(ddraw);
@@ -4974,7 +4987,7 @@ static void test_rt_caps(void)
 
     memset(palette_entries, 0, sizeof(palette_entries));
     hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
-    ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
+    ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
 
     for (i = 0; i < ARRAY_SIZE(test_data); ++i)
     {
@@ -4999,34 +5012,50 @@ static void test_rt_caps(void)
         surface_desc.dwWidth = 640;
         surface_desc.dwHeight = 480;
         hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
-        ok(SUCCEEDED(hr) || broken(test_data[i].create_may_fail),
-                "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
-                i, test_data[i].caps_in, hr);
+        ok(hr == DD_OK || broken(test_data[i].create_may_fail),
+                "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
         if (FAILED(hr))
             continue;
 
         memset(&surface_desc, 0, sizeof(surface_desc));
         surface_desc.dwSize = sizeof(surface_desc);
         hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
-        ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
-        ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
-                "Test %u: Got unexpected caps %#x, expected %#x.\n",
-                i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
+        ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
+        ok(test_data[i].caps_out == ~0u || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
+                "Got unexpected caps %#x, expected %#x, test %u, software_device %u.\n",
+                surface_desc.ddsCaps.dwCaps, test_data[i].caps_out, i, software_device);
+
+        hr = IDirect3D2_CreateDevice(d3d, device_guid, surface, &device);
+
+        todo_wine_if(software_device && test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM)
+        ok((!software_device && hr == test_data[i].create_device_hr)
+                || (software_device && (hr == (test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM
+                ? DD_OK : test_data[i].create_device_hr))),
+                "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
 
-        hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
-        ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
-                i, hr, test_data[i].create_device_hr);
         if (FAILED(hr))
         {
             if (hr == DDERR_NOPALETTEATTACHED)
             {
                 hr = IDirectDrawSurface_SetPalette(surface, palette);
-                ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
-                hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
-                if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
-                    ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+                ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
+                hr = IDirect3D2_CreateDevice(d3d, device_guid, surface, &device);
+                if (software_device)
+                    todo_wine
+                    ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n",
+                            hr, i, software_device);
+                else if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
+                    ok(hr == DDERR_INVALIDPIXELFORMAT, "Got unexpected hr %#x, test %u, software_device %u.\n",
+                            hr, i, software_device);
                 else
-                    ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
+                    ok(hr == D3DERR_SURFACENOTINVIDMEM, "Got unexpected hr %#x, test %u, software_device %u.\n",
+                            hr, i, software_device);
+
+                if (hr == DD_OK)
+                {
+                    refcount = IDirect3DDevice2_Release(device);
+                    ok(!refcount, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
+                }
             }
             IDirectDrawSurface_Release(surface);
 
@@ -5037,10 +5066,10 @@ static void test_rt_caps(void)
             surface_desc.dwWidth = 640;
             surface_desc.dwHeight = 480;
             hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
-            ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
+            ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
 
-            hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
-            ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
+            hr = IDirect3D2_CreateDevice(d3d, device_guid, surface, &device);
+            ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
         }
 
         memset(&surface_desc, 0, sizeof(surface_desc));
@@ -5060,13 +5089,14 @@ static void test_rt_caps(void)
         surface_desc.dwWidth = 640;
         surface_desc.dwHeight = 480;
         hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &rt, NULL);
-        ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
-                i, test_data[i].caps_in, hr);
+        ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
 
         hr = IDirect3DDevice2_SetRenderTarget(device, rt, 0);
-        ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
-                "Test %u: Got unexpected hr %#x, expected %#x.\n",
-                i, hr, test_data[i].set_rt_hr);
+        ok(hr == test_data[i].set_rt_hr  || (software_device && hr == DDERR_NOPALETTEATTACHED)
+                || broken(hr == test_data[i].alternative_set_rt_hr),
+                "Got unexpected hr %#x, test %u, software_device %u.\n",
+                hr, i, software_device);
+
         if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
             expected_rt = rt;
         else
@@ -5081,8 +5111,8 @@ static void test_rt_caps(void)
         }
 
         hr = IDirect3DDevice2_GetRenderTarget(device, &tmp);
-        ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
-        ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
+        ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
+        ok(tmp == expected_rt, "Got unexpected rt %p, test %u, software_device %u.\n", tmp, i, software_device);
 
         IDirectDrawSurface_Release(tmp);
         IDirectDrawSurface_Release(rt);
@@ -15211,6 +15241,12 @@ done:
     IDirectDraw2_Release(ddraw);
 }
 
+static void run_for_each_device_type(void (*test_func)(const GUID *))
+{
+    test_func(&IID_IDirect3DHALDevice);
+    test_func(&IID_IDirect3DRGBDevice);
+}
+
 START_TEST(ddraw2)
 {
     DDDEVICEIDENTIFIER identifier;
@@ -15276,7 +15312,7 @@ START_TEST(ddraw2)
     test_lighting_interface_versions();
     test_coop_level_activateapp();
     test_unsupported_formats();
-    test_rt_caps();
+    run_for_each_device_type(test_rt_caps);
     test_primary_caps();
     test_surface_lock();
     test_surface_discard();
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index f009b4583f4..7e1c9837243 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -164,6 +164,11 @@ static BOOL ddraw_is_vmware(IDirectDraw4 *ddraw)
     return ddraw_is_vendor(ddraw, 0x15ad);
 }
 
+static BOOL is_software_device_type(const GUID *device_guid)
+{
+    return device_guid != &IID_IDirect3DHALDevice;
+}
+
 static IDirectDrawSurface4 *create_overlay(IDirectDraw4 *ddraw,
         unsigned int width, unsigned int height, DWORD format)
 {
@@ -6355,10 +6360,12 @@ static void test_unsupported_formats(void)
     DestroyWindow(window);
 }
 
-static void test_rt_caps(void)
+static void test_rt_caps(const GUID *device_guid)
 {
     PALETTEENTRY palette_entries[256];
     IDirectDrawPalette *palette;
+    BOOL software_device;
+    DWORD expected_caps;
     IDirectDraw4 *ddraw;
     DDPIXELFORMAT z_fmt;
     IDirect3D3 *d3d;
@@ -6377,7 +6384,7 @@ static void test_rt_caps(void)
     {
         const DDPIXELFORMAT *pf;
         DWORD caps_in;
-        DWORD caps_out;
+        DWORD caps_out[2];
         DWORD caps2_in;
         DWORD caps2_out;
         HRESULT create_device_hr;
@@ -6388,7 +6395,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,},
             0,
             0,
             D3D_OK,
@@ -6398,7 +6405,8 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+                    DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             D3D_OK,
@@ -6408,7 +6416,8 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_OFFSCREENPLAIN,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+                    DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6418,7 +6427,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE},
             0,
             0,
             D3DERR_SURFACENOTINVIDMEM,
@@ -6428,7 +6437,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6438,7 +6447,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
-            DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM},
             0,
             0,
             D3D_OK,
@@ -6448,7 +6457,8 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_3DDEVICE,
-            DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+                    DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             D3D_OK,
@@ -6458,7 +6468,8 @@ static void test_rt_caps(void)
         {
             NULL,
             0,
-            DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+                    DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6468,7 +6479,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
-            DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
+            {DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE},
             0,
             0,
             D3DERR_SURFACENOTINVIDMEM,
@@ -6478,7 +6489,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_SYSTEMMEMORY,
-            DDSCAPS_SYSTEMMEMORY,
+            {DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6488,7 +6499,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE,
-            DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY,
+            {DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY},
             DDSCAPS2_TEXTUREMANAGE,
             DDSCAPS2_TEXTUREMANAGE,
             D3DERR_SURFACENOTINVIDMEM,
@@ -6498,7 +6509,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE,
-            DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY,
+            {DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY},
             DDSCAPS2_D3DTEXTUREMANAGE,
             DDSCAPS2_D3DTEXTUREMANAGE,
             D3DERR_SURFACENOTINVIDMEM,
@@ -6508,7 +6519,7 @@ static void test_rt_caps(void)
         {
             &p8_fmt,
             0,
-            DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6518,7 +6529,7 @@ static void test_rt_caps(void)
         {
             &p8_fmt,
             DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
-            ~0U /* AMD r200 */,
+            {~0u /* AMD r200 */, DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             DDERR_NOPALETTEATTACHED,
@@ -6528,7 +6539,8 @@ static void test_rt_caps(void)
         {
             &p8_fmt,
             DDSCAPS_OFFSCREENPLAIN,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+                    DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6538,7 +6550,7 @@ static void test_rt_caps(void)
         {
             &p8_fmt,
             DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE},
             0,
             0,
             DDERR_NOPALETTEATTACHED,
@@ -6548,7 +6560,7 @@ static void test_rt_caps(void)
         {
             &p8_fmt,
             DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6558,7 +6570,7 @@ static void test_rt_caps(void)
         {
             &z_fmt,
             DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
-            DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6568,7 +6580,8 @@ static void test_rt_caps(void)
         {
             &z_fmt,
             DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
-            DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
+                    DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6578,7 +6591,8 @@ static void test_rt_caps(void)
         {
             &z_fmt,
             DDSCAPS_ZBUFFER,
-            DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
+                    DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6588,7 +6602,7 @@ static void test_rt_caps(void)
         {
             &z_fmt,
             DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
-            DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
+            {DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6598,7 +6612,7 @@ static void test_rt_caps(void)
         {
             &z_fmt,
             DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
-            DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
+            {DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6607,11 +6621,13 @@ static void test_rt_caps(void)
         },
     };
 
+    software_device = is_software_device_type(device_guid);
+
     window = create_window();
     ddraw = create_ddraw();
     ok(!!ddraw, "Failed to create a ddraw object.\n");
     hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
-    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
 
     if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
     {
@@ -6620,17 +6636,17 @@ static void test_rt_caps(void)
     }
 
     memset(&z_fmt, 0, sizeof(z_fmt));
-    hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
+    hr = IDirect3D3_EnumZBufferFormats(d3d, device_guid, enum_z_fmt, &z_fmt);
     if (FAILED(hr) || !z_fmt.dwSize)
     {
-        skip("No depth buffer formats available, skipping test.\n");
+        skip("No depth buffer formats available, software_device %u, skipping test.\n", software_device);
         IDirect3D3_Release(d3d);
         goto done;
     }
 
     memset(palette_entries, 0, sizeof(palette_entries));
     hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
-    ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
+    ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
 
     for (i = 0; i < ARRAY_SIZE(test_data); ++i)
     {
@@ -6651,34 +6667,71 @@ static void test_rt_caps(void)
         surface_desc.dwWidth = 640;
         surface_desc.dwHeight = 480;
         hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
-        ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x and caps2 %#x, hr %#x.\n",
-           i, test_data[i].caps_in, test_data[i].caps2_in, hr);
+        if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY && hr == DDERR_NODIRECTDRAWHW)
+        {
+            skip("No 3d hardware, skipping test %u, software_device %u.\n", i, software_device);
+            continue;
+        }
+        ok(hr == DD_OK || (software_device && (surface_desc.ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER))
+                == (DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER) && hr == DDERR_UNSUPPORTED)
+                || broken(software_device && test_data[i].pf == &p8_fmt && hr == DDERR_INVALIDPIXELFORMAT),
+                "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
+        if (FAILED(hr))
+            continue;
 
         memset(&surface_desc, 0, sizeof(surface_desc));
         surface_desc.dwSize = sizeof(surface_desc);
         hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
-        ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
-        ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
-                "Test %u: Got unexpected caps %#x, expected %#x.\n",
-                i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
+        ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
+
+        if (software_device)
+        {
+            expected_caps = test_data[i].caps_out[software_device]
+                    ? test_data[i].caps_out[software_device] : test_data[i].caps_out[0];
+
+            ok(surface_desc.ddsCaps.dwCaps == expected_caps
+                    || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out[0],
+                    "Got unexpected caps %#x, test %u, software_device %u.\n",
+                    surface_desc.ddsCaps.dwCaps, i, software_device);
+        }
+        else
+        {
+            ok(test_data[i].caps_out[0] == ~0u || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out[0],
+                    "Got unexpected caps %#x, expected %#x, test %u, software_device %u.\n",
+                    surface_desc.ddsCaps.dwCaps, test_data[i].caps_out[0], i, software_device);
+        }
         ok(surface_desc.ddsCaps.dwCaps2 == test_data[i].caps2_out,
-           "Test %u: Got unexpected caps2 %#x, expected %#x.\n",
-           i, surface_desc.ddsCaps.dwCaps2, test_data[i].caps2_out);
+                "Got unexpected caps2 %#x, expected %#x, test %u, software_device %u.\n",
+                surface_desc.ddsCaps.dwCaps2, test_data[i].caps2_out, i, software_device);
+
+        hr = IDirect3D3_CreateDevice(d3d, device_guid, surface, &device, NULL);
 
-        hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
-        ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
-                i, hr, test_data[i].create_device_hr);
+        todo_wine_if(software_device && test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM)
+        ok((!software_device && hr == test_data[i].create_device_hr)
+                || (software_device && (hr == (test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM
+                ? DD_OK : test_data[i].create_device_hr))),
+                "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
         if (FAILED(hr))
         {
             if (hr == DDERR_NOPALETTEATTACHED)
             {
                 hr = IDirectDrawSurface4_SetPalette(surface, palette);
-                ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
-                hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
+                ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
+                if (software_device)
+                {
+                    /* _CreateDevice succeeds with software device, but the palette gets extra reference
+                     * on Windows (probably due to a bug) which doesn't go away on the device and surface
+                     * destruction and ddraw is not destroyed cleanly, so skipping this test. */
+                    IDirectDrawSurface4_Release(surface);
+                    continue;
+                }
+                hr = IDirect3D3_CreateDevice(d3d, device_guid, surface, &device, NULL);
                 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
-                    ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+                    ok(hr == DDERR_INVALIDPIXELFORMAT, "Got unexpected hr %#x, test %u, software_device %u.\n",
+                            hr, i, software_device);
                 else
-                    ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
+                    ok(hr == D3DERR_SURFACENOTINVIDMEM, "Got unexpected hr %#x, test %u, software_device %u.\n",
+                            hr, i, software_device);
             }
             IDirectDrawSurface4_Release(surface);
 
@@ -6689,10 +6742,10 @@ static void test_rt_caps(void)
             surface_desc.dwWidth = 640;
             surface_desc.dwHeight = 480;
             hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
-            ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
+            ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
 
-            hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
-            ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
+            hr = IDirect3D3_CreateDevice(d3d, device_guid, surface, &device, NULL);
+            ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
         }
 
         memset(&surface_desc, 0, sizeof(surface_desc));
@@ -6708,21 +6761,21 @@ static void test_rt_caps(void)
         surface_desc.dwWidth = 640;
         surface_desc.dwHeight = 480;
         hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &rt, NULL);
-        ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
-                i, test_data[i].caps_in, hr);
+        ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
 
         hr = IDirect3DDevice3_SetRenderTarget(device, rt, 0);
-        ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
-                "Test %u: Got unexpected hr %#x, expected %#x.\n",
-                i, hr, test_data[i].set_rt_hr);
+        ok(hr == test_data[i].set_rt_hr || (software_device && hr == DDERR_NOPALETTEATTACHED)
+                || broken(hr == test_data[i].alternative_set_rt_hr),
+                "Got unexpected hr %#x, test %u, software_device %u.\n",
+                hr, i, software_device);
         if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
             expected_rt = rt;
         else
             expected_rt = surface;
 
         hr = IDirect3DDevice3_GetRenderTarget(device, &tmp);
-        ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
-        ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
+        ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
+        ok(tmp == expected_rt, "Got unexpected rt %p, test %u, software_device %u.\n", tmp, i, software_device);
 
         IDirectDrawSurface4_Release(tmp);
         IDirectDrawSurface4_Release(rt);
@@ -6732,7 +6785,8 @@ static void test_rt_caps(void)
         ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
     }
 
-    IDirectDrawPalette_Release(palette);
+    refcount = IDirectDrawPalette_Release(palette);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
     IDirect3D3_Release(d3d);
 
 done:
@@ -18271,6 +18325,12 @@ done:
     IDirectDraw4_Release(ddraw);
 }
 
+static void run_for_each_device_type(void (*test_func)(const GUID *))
+{
+    test_func(&IID_IDirect3DHALDevice);
+    test_func(&IID_IDirect3DRGBDevice);
+}
+
 START_TEST(ddraw4)
 {
     DDDEVICEIDENTIFIER identifier;
@@ -18343,7 +18403,7 @@ START_TEST(ddraw4)
     test_texturemanage();
     test_block_formats_creation();
     test_unsupported_formats();
-    test_rt_caps();
+    run_for_each_device_type(test_rt_caps);
     test_primary_caps();
     test_surface_lock();
     test_surface_discard();
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index 628360630dc..68f68ef6446 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -30,6 +30,7 @@ HRESULT WINAPI GetSurfaceFromDC(HDC dc, struct IDirectDrawSurface **surface, HDC
 static HRESULT (WINAPI *pDirectDrawCreateEx)(GUID *guid, void **ddraw, REFIID iid, IUnknown *outer_unknown);
 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
 static DEVMODEW registry_mode;
+static const GUID *hw_device_guid = &IID_IDirect3DHALDevice;
 
 static HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *);
 
@@ -190,6 +191,11 @@ static BOOL ddraw_is_amd(IDirectDraw7 *ddraw)
     return ddraw_is_vendor(ddraw, 0x1002);
 }
 
+static BOOL is_software_device_type(const GUID *device_guid)
+{
+    return device_guid != &IID_IDirect3DTnLHalDevice && device_guid != &IID_IDirect3DHALDevice;
+}
+
 static IDirectDrawSurface7 *create_overlay(IDirectDraw7 *ddraw,
         unsigned int width, unsigned int height, DWORD format)
 {
@@ -6085,13 +6091,13 @@ static void test_unsupported_formats(void)
     DestroyWindow(window);
 }
 
-static void test_rt_caps(void)
+static void test_rt_caps(const GUID *device_guid)
 {
-    const GUID *devtype = &IID_IDirect3DHALDevice;
     PALETTEENTRY palette_entries[256];
     IDirectDrawPalette *palette;
+    BOOL software_device;
+    DWORD expected_caps;
     IDirectDraw7 *ddraw;
-    BOOL hal_ok = FALSE;
     DDPIXELFORMAT z_fmt;
     IDirect3D7 *d3d;
     unsigned int i;
@@ -6109,7 +6115,7 @@ static void test_rt_caps(void)
     {
         const DDPIXELFORMAT *pf;
         DWORD caps_in;
-        DWORD caps_out;
+        DWORD caps_out[2];
         DWORD caps2_in;
         DWORD caps2_out;
         HRESULT create_device_hr;
@@ -6120,7 +6126,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,},
             0,
             0,
             D3D_OK,
@@ -6130,7 +6136,8 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+                    DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             D3D_OK,
@@ -6140,7 +6147,8 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_OFFSCREENPLAIN,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+                    DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6150,7 +6158,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE},
             0,
             0,
             D3DERR_SURFACENOTINVIDMEM,
@@ -6160,7 +6168,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6170,7 +6178,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
-            DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM},
             0,
             0,
             D3D_OK,
@@ -6180,7 +6188,8 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_3DDEVICE,
-            DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+                    DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             D3D_OK,
@@ -6190,7 +6199,7 @@ static void test_rt_caps(void)
         {
             NULL,
             0,
-            DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM, DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6200,7 +6209,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
-            DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
+            {DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE},
             0,
             0,
             D3DERR_SURFACENOTINVIDMEM,
@@ -6210,7 +6219,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_SYSTEMMEMORY,
-            DDSCAPS_SYSTEMMEMORY,
+            {DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6220,7 +6229,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE,
-            DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY,
+            {DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY},
             DDSCAPS2_TEXTUREMANAGE,
             DDSCAPS2_TEXTUREMANAGE,
             D3DERR_SURFACENOTINVIDMEM,
@@ -6230,7 +6239,7 @@ static void test_rt_caps(void)
         {
             NULL,
             DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE,
-            DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY,
+            {DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY},
             DDSCAPS2_D3DTEXTUREMANAGE,
             DDSCAPS2_D3DTEXTUREMANAGE,
             D3DERR_SURFACENOTINVIDMEM,
@@ -6240,7 +6249,7 @@ static void test_rt_caps(void)
         {
             &p8_fmt,
             0,
-            DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6250,7 +6259,7 @@ static void test_rt_caps(void)
         {
             &p8_fmt,
             DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
-            ~0U /* AMD r200 */,
+            {~0u /* AMD r200 */, DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             DDERR_NOPALETTEATTACHED,
@@ -6260,7 +6269,8 @@ static void test_rt_caps(void)
         {
             &p8_fmt,
             DDSCAPS_OFFSCREENPLAIN,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
+                    DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6270,7 +6280,7 @@ static void test_rt_caps(void)
         {
             &p8_fmt,
             DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE},
             0,
             0,
             DDERR_NOPALETTEATTACHED,
@@ -6280,7 +6290,7 @@ static void test_rt_caps(void)
         {
             &p8_fmt,
             DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
-            DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
+            {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6290,7 +6300,7 @@ static void test_rt_caps(void)
         {
             &z_fmt,
             DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
-            DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6300,7 +6310,8 @@ static void test_rt_caps(void)
         {
             &z_fmt,
             DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
-            DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
+                    DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6310,7 +6321,8 @@ static void test_rt_caps(void)
         {
             &z_fmt,
             DDSCAPS_ZBUFFER,
-            DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
+            {DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
+                    DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6320,7 +6332,7 @@ static void test_rt_caps(void)
         {
             &z_fmt,
             DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
-            DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
+            {DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6330,7 +6342,7 @@ static void test_rt_caps(void)
         {
             &z_fmt,
             DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
-            DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
+            {DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER},
             0,
             0,
             DDERR_INVALIDCAPS,
@@ -6339,6 +6351,8 @@ static void test_rt_caps(void)
         },
     };
 
+    software_device = is_software_device_type(device_guid);
+
     window = create_window();
     ddraw = create_ddraw();
     ok(!!ddraw, "Failed to create a ddraw object.\n");
@@ -6351,23 +6365,18 @@ static void test_rt_caps(void)
         goto done;
     }
 
-    hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
-    ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
-    if (hal_ok)
-        devtype = &IID_IDirect3DTnLHalDevice;
-
     memset(&z_fmt, 0, sizeof(z_fmt));
-    hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
+    hr = IDirect3D7_EnumZBufferFormats(d3d, device_guid, enum_z_fmt, &z_fmt);
     if (FAILED(hr) || !z_fmt.dwSize)
     {
-        skip("No depth buffer formats available, skipping test.\n");
+        skip("No depth buffer formats available, software_device %u, skipping test.\n", software_device);
         IDirect3D7_Release(d3d);
         goto done;
     }
 
     memset(palette_entries, 0, sizeof(palette_entries));
     hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
-    ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
+    ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
 
     for (i = 0; i < ARRAY_SIZE(test_data); ++i)
     {
@@ -6388,34 +6397,68 @@ static void test_rt_caps(void)
         surface_desc.dwWidth = 640;
         surface_desc.dwHeight = 480;
         hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
-        ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x and caps2 %#x, hr %#x.\n",
-           i, test_data[i].caps_in, test_data[i].caps2_in, hr);
+        if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY && hr == DDERR_NODIRECTDRAWHW)
+        {
+            skip("No 3d hardware, skipping test %u, software_device %u.\n", i, software_device);
+            continue;
+        }
+        ok(hr == DD_OK || (software_device && (surface_desc.ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER))
+                == (DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER) && hr == DDERR_UNSUPPORTED)
+                || broken(software_device && test_data[i].pf == &p8_fmt && hr == DDERR_INVALIDPIXELFORMAT),
+                "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
+        if (FAILED(hr))
+            continue;
 
         memset(&surface_desc, 0, sizeof(surface_desc));
         surface_desc.dwSize = sizeof(surface_desc);
         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
-        ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
-        ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
-                "Test %u: Got unexpected caps %#x, expected %#x.\n",
-                i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
-        ok(surface_desc.ddsCaps.dwCaps2 == test_data[i].caps2_out,
-           "Test %u: Got unexpected caps2 %#x, expected %#x.\n",
-           i, surface_desc.ddsCaps.dwCaps2, test_data[i].caps2_out);
+        ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
 
-        hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
-        ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
-                i, hr, test_data[i].create_device_hr);
+        if (software_device)
+        {
+            expected_caps = test_data[i].caps_out[software_device]
+                    ? test_data[i].caps_out[software_device] : test_data[i].caps_out[0];
+
+            todo_wine_if(test_data[i].caps_out[software_device]
+                    && surface_desc.ddsCaps.dwCaps == test_data[i].caps_out[0])
+            ok(surface_desc.ddsCaps.dwCaps == expected_caps
+                    || broken(surface_desc.ddsCaps.dwCaps == test_data[i].caps_out[0]),
+                    "Got unexpected caps %#x, test %u, software_device %u.\n",
+                    surface_desc.ddsCaps.dwCaps, i, software_device);
+        }
+        else
+        {
+            ok(test_data[i].caps_out[0] == ~0u || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out[0],
+                    "Got unexpected caps %#x, expected %#x, test %u, software_device %u.\n",
+                    surface_desc.ddsCaps.dwCaps, test_data[i].caps_out[0], i, software_device);
+        }
+        ok(surface_desc.ddsCaps.dwCaps2 == test_data[i].caps2_out,
+                "Got unexpected caps2 %#x, expected %#x, test %u, software_device %u.\n",
+                surface_desc.ddsCaps.dwCaps2, test_data[i].caps2_out, i, software_device);
+
+        hr = IDirect3D7_CreateDevice(d3d, device_guid, surface, &device);
+        todo_wine_if(software_device && test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM)
+        ok((!software_device && hr == test_data[i].create_device_hr)
+                || (software_device && (hr == (test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM
+                ? DD_OK : test_data[i].create_device_hr))),
+                "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
         if (FAILED(hr))
         {
             if (hr == DDERR_NOPALETTEATTACHED)
             {
                 hr = IDirectDrawSurface7_SetPalette(surface, palette);
-                ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
-                hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
+                ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
+                hr = IDirect3D7_CreateDevice(d3d, device_guid, surface, &device);
                 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
-                    ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
+                    ok(hr == DDERR_INVALIDPIXELFORMAT, "Got unexpected hr %#x, test %u, software_device %u.\n",
+                            hr, i, software_device);
+                else if (software_device)
+                    todo_wine
+                    ok(hr == E_FAIL, "Got unexpected hr %#x, test %u, software_device %u.\n",
+                            hr, i, software_device);
                 else
-                    ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
+                    ok(hr == D3DERR_SURFACENOTINVIDMEM, "Got unexpected hr %#x, test %u, software_device %u.\n",
+                            hr, i, software_device);
             }
             IDirectDrawSurface7_Release(surface);
 
@@ -6426,10 +6469,10 @@ static void test_rt_caps(void)
             surface_desc.dwWidth = 640;
             surface_desc.dwHeight = 480;
             hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
-            ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
+            ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
 
-            hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
-            ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
+            hr = IDirect3D7_CreateDevice(d3d, device_guid, surface, &device);
+            ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
         }
 
         memset(&surface_desc, 0, sizeof(surface_desc));
@@ -6445,21 +6488,21 @@ static void test_rt_caps(void)
         surface_desc.dwWidth = 640;
         surface_desc.dwHeight = 480;
         hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL);
-        ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
-                i, test_data[i].caps_in, hr);
+        ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
 
         hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
-        ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
-                "Test %u: Got unexpected hr %#x, expected %#x.\n",
-                i, hr, test_data[i].set_rt_hr);
+        ok(hr == test_data[i].set_rt_hr || (software_device && hr == DDERR_NOPALETTEATTACHED)
+                || broken(hr == test_data[i].alternative_set_rt_hr),
+                "Got unexpected hr %#x, test %u, software_device %u.\n",
+                hr, i, software_device);
         if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
             expected_rt = rt;
         else
             expected_rt = surface;
 
         hr = IDirect3DDevice7_GetRenderTarget(device, &tmp);
-        ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
-        ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
+        ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
+        ok(tmp == expected_rt, "Got unexpected rt %p, test %u, software_device %u.\n", tmp, i, software_device);
 
         IDirectDrawSurface7_Release(tmp);
         IDirectDrawSurface7_Release(rt);
@@ -6469,7 +6512,8 @@ static void test_rt_caps(void)
         ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
     }
 
-    IDirectDrawPalette_Release(palette);
+    refcount = IDirectDrawPalette_Release(palette);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
     IDirect3D7_Release(d3d);
 
 done:
@@ -18533,12 +18577,21 @@ done:
     IDirectDraw7_Release(ddraw);
 }
 
+static void run_for_each_device_type(void (*test_func)(const GUID *))
+{
+    test_func(hw_device_guid);
+    test_func(&IID_IDirect3DRGBDevice);
+}
+
 START_TEST(ddraw7)
 {
     DDDEVICEIDENTIFIER2 identifier;
     HMODULE module, dwmapi;
     DEVMODEW current_mode;
     IDirectDraw7 *ddraw;
+    IDirect3D7 *d3d;
+    BOOL hal_ok;
+    HRESULT hr;
 
     module = GetModuleHandleA("ddraw.dll");
     if (!(pDirectDrawCreateEx = (void *)GetProcAddress(module, "DirectDrawCreateEx")))
@@ -18561,6 +18614,20 @@ START_TEST(ddraw7)
                 HIWORD(U(identifier.liDriverVersion).HighPart), LOWORD(U(identifier.liDriverVersion).HighPart),
                 HIWORD(U(identifier.liDriverVersion).LowPart), LOWORD(U(identifier.liDriverVersion).LowPart));
     }
+
+    if (IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d) == DD_OK)
+    {
+        hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
+        ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+        if (hal_ok)
+            hw_device_guid = &IID_IDirect3DTnLHalDevice;
+        IDirectDraw7_Release(d3d);
+    }
+    else
+    {
+        trace("D3D interface is not available.\n");
+    }
+
     IDirectDraw7_Release(ddraw);
 
     memset(&current_mode, 0, sizeof(current_mode));
@@ -18612,7 +18679,7 @@ START_TEST(ddraw7)
     test_texturemanage();
     test_block_formats_creation();
     test_unsupported_formats();
-    test_rt_caps();
+    run_for_each_device_type(test_rt_caps);
     test_primary_caps();
     test_surface_lock();
     test_surface_discard();
-- 
2.29.2




More information about the wine-devel mailing list