From 8f3d4f8c59a55915fb9e9ff2242759a04d28a94e Mon Sep 17 00:00:00 2001
From: Michael Müller <michael@fds-team.de>
Date: Thu, 18 Feb 2021 18:02:12 -1000
Subject: [PATCH] ddraw: HWTRANSFORMANDLIGHT is not set for software devices

Signed-off-by: Michael Müller <michael@fds-team.de>
Signed-off-by: David Adam <daadad0022@gmail.com>
---
 dlls/ddraw/ddraw.c        |  8 ++++++++
 dlls/ddraw/tests/ddraw1.c | 35 +++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw2.c | 33 +++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw4.c | 33 +++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw7.c | 26 ++++++++++++++++++++++++++
 5 files changed, 135 insertions(+)

diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index d616330c307..8a0196e6d8f 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -49,6 +49,7 @@ static struct enum_device_entry
     char interface_name[100];
     char device_name[100];
     const GUID *device_guid;
+    const DWORD unset_device_caps;
 } device_list7[] =
 {
     /* T&L HAL device */
@@ -56,6 +57,7 @@ static struct enum_device_entry
         "WINE Direct3D7 Hardware Transform and Lighting acceleration using WineD3D",
         "Wine D3D7 T&L HAL",
         &IID_IDirect3DTnLHalDevice,
+        0,
     },
 
     /* HAL device */
@@ -63,6 +65,7 @@ static struct enum_device_entry
         "WINE Direct3D7 Hardware acceleration using WineD3D",
         "Direct3D HAL",
         &IID_IDirect3DHALDevice,
+        0,
     },
 
     /* RGB device */
@@ -70,6 +73,7 @@ static struct enum_device_entry
         "WINE Direct3D7 RGB Software Emulation using WineD3D",
         "Wine D3D7 RGB",
         &IID_IDirect3DRGBDevice,
+        D3DDEVCAPS_HWTRANSFORMANDLIGHT,
     },
 };
 
@@ -3770,6 +3774,7 @@ static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBA
         HRESULT ret;
 
         device_desc7.deviceGUID = *device_list7[i].device_guid;
+        device_desc7.dwDevCaps = ~device_list7[i].unset_device_caps;
         ret = callback(device_list7[i].interface_name, device_list7[i].device_name, &device_desc7, context);
         if (ret != DDENUMRET_OK)
         {
@@ -3868,6 +3873,9 @@ static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBA
         /* RGB, RAMP and MMX devices cannot report HAL hardware flags */
         hal_desc.dwFlags = 0;
 
+        hal_desc.dwDevCaps = ~D3DDEVCAPS_HWTRANSFORMANDLIGHT;
+        hel_desc.dwDevCaps = ~D3DDEVCAPS_HWTRANSFORMANDLIGHT;
+
         hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description,
                 device_name, &hal_desc, &hel_desc, context);
         if (hr != D3DENUMRET_OK)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index df5c8ac8400..120e2b2a947 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -14284,6 +14284,40 @@ static void test_get_display_mode(void)
     IDirectDraw_Release(ddraw);
 }
 
+static HRESULT WINAPI softwaretransformlight_Callback(GUID *Guid, char *DeviceDescription,
+        char *DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, void *ctx)
+{
+    if (IsEqualGUID(&IID_IDirect3DRGBDevice, Guid) || IsEqualGUID(&IID_IDirect3DMMXDevice, Guid))
+    {
+        /* Wine asserts wrong assumption about enumeration of RGB devices in ddraw version 1.
+           When this assumption is fixed, these tests will pass */
+        todo_wine ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
+           "Software device should not advertise HWTRANSFORMANDLIGHT in HAL\n");
+        todo_wine ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
+           "Software device should not advertise HWTRANSFORMANDLIGHT in HEL\n");
+    }
+
+    return DDENUMRET_OK;
+}
+
+static void test_softwaretransformlight(void)
+{
+    IDirectDraw *ddraw;
+    IDirect3D *d3d;
+    HRESULT hr;
+
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+    hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
+    ok(hr == DD_OK, "Failed to get d3d interface, hr %#x.\n", hr);
+
+    hr = IDirect3D_EnumDevices(d3d, softwaretransformlight_Callback, NULL);
+    ok(hr == D3D_OK, "EnumDevice failed, hr %#x.\n", hr);
+
+    IDirect3D_Release(d3d);
+    IDirectDraw_Release(ddraw);
+}
+
 START_TEST(ddraw1)
 {
     DDDEVICEIDENTIFIER identifier;
@@ -14400,4 +14434,5 @@ START_TEST(ddraw1)
     test_vtbl_protection();
     test_window_position();
     test_get_display_mode();
+    test_softwaretransformlight();
 }
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index bc915c97864..67ca0bee4aa 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -15211,6 +15211,38 @@ done:
     IDirectDraw2_Release(ddraw);
 }
 
+static HRESULT WINAPI softwaretransformlight_Callback(GUID *Guid, char *DeviceDescription,
+        char *DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, void *ctx)
+{
+    if(IsEqualGUID(&IID_IDirect3DRGBDevice, Guid) || IsEqualGUID(&IID_IDirect3DMMXDevice, Guid))
+    {
+        ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
+           "Software device should not advertise HWTRANSFORMANDLIGHT in HAL\n");
+        ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
+           "Software device should not advertise HWTRANSFORMANDLIGHT in HEL\n");
+    }
+
+    return DDENUMRET_OK;
+}
+
+static void test_softwaretransformlight(void)
+{
+    IDirectDraw2 *ddraw;
+    IDirect3D2 *d3d2;
+    HRESULT hr;
+
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+    hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d2);
+    ok(hr == DD_OK, "Failed to get d3d interface, hr %#x.\n", hr);
+
+    hr = IDirect3D2_EnumDevices(d3d2, softwaretransformlight_Callback, NULL);
+    ok(hr == D3D_OK, "EnumDevice failed, hr %#x.\n", hr);
+
+    IDirect3D2_Release(d3d2);
+    IDirectDraw2_Release(ddraw);
+}
+
 START_TEST(ddraw2)
 {
     DDDEVICEIDENTIFIER identifier;
@@ -15333,4 +15365,5 @@ START_TEST(ddraw2)
     test_cursor_clipping();
     test_window_position();
     test_get_display_mode();
+    test_softwaretransformlight();
 }
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index f009b4583f4..6819f08d8a1 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -18271,6 +18271,38 @@ done:
     IDirectDraw4_Release(ddraw);
 }
 
+static HRESULT WINAPI softwaretransformlight_Callback(GUID *Guid, char *DeviceDescription,
+        char *DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, void *ctx)
+{
+    if (IsEqualGUID(&IID_IDirect3DRGBDevice, Guid) || IsEqualGUID(&IID_IDirect3DMMXDevice, Guid))
+    {
+        ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
+           "Software device should not advertise HWTRANSFORMANDLIGHT in HAL\n");
+        ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
+           "Software device should not advertise HWTRANSFORMANDLIGHT in HEL\n");
+    }
+
+    return DDENUMRET_OK;
+}
+
+static void test_softwaretransformlight(void)
+{
+    IDirectDraw4 *ddraw;
+    IDirect3D2 *d3d3;
+    HRESULT hr;
+
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+    hr = IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d3);
+    ok(hr == DD_OK, "Failed to get d3d interface, hr %#x.\n", hr);
+
+    hr = IDirect3D3_EnumDevices(d3d3, softwaretransformlight_Callback, NULL);
+    ok(hr == D3D_OK, "EnumDevice failed, hr %#x.\n", hr);
+
+    IDirect3D3_Release(d3d3);
+    IDirectDraw4_Release(ddraw);
+}
+
 START_TEST(ddraw4)
 {
     DDDEVICEIDENTIFIER identifier;
@@ -18409,4 +18441,5 @@ START_TEST(ddraw4)
     test_cursor_clipping();
     test_window_position();
     test_get_display_mode();
+    test_softwaretransformlight();
 }
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index 613f8dae98b..1b571b4fbfc 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -18533,6 +18533,31 @@ done:
     IDirectDraw7_Release(ddraw);
 }
 
+static HRESULT WINAPI softwaretransformlight_Callback(char *DeviceDescription, char *DeviceName,
+        D3DDEVICEDESC7 *device_desc, void *ctx)
+{
+    if (IsEqualGUID(&IID_IDirect3DRGBDevice, &device_desc->deviceGUID) || IsEqualGUID(&IID_IDirect3DMMXDevice, &device_desc->deviceGUID))
+        ok((device_desc->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
+            "Software device should not advertise HWTRANSFORMANDLIGHT\n");
+
+    return DDENUMRET_OK;
+}
+
+static void test_softwaretransformlight(void)
+{
+    IDirectDraw7 *ddraw;
+    IDirect3D7 *d3d7;
+    HRESULT hr;
+
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+    hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d7);
+    ok(hr == DD_OK, "Failed to get d7d interface, hr %#x.\n", hr);
+
+     hr = IDirect3D7_EnumDevices(d3d7, softwaretransformlight_Callback, NULL);
+     ok(hr == D3D_OK, "IDirect3D_EnumDevices returned 0x%08x\n", hr);
+}
+
 START_TEST(ddraw7)
 {
     DDDEVICEIDENTIFIER2 identifier;
@@ -18686,4 +18711,5 @@ START_TEST(ddraw7)
     test_cursor_clipping();
     test_window_position();
     test_get_display_mode();
+    test_softwaretransformlight();
 }
-- 
2.27.0

