[PATCH v2 2/3] ddraw: Fix conversion of v2 viewport from v1 in d3d_viewport_GetViewport2().

Paul Gofman gofmanp at gmail.com
Tue Nov 26 12:19:49 CST 2019


Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
    v2:
        - add todo_wine to now failing tests in d3d.c.

    It looks like the conversion between viewport types is the same between d3d versions
    (the test for ddraw1 in the next patch shows that). The handling of invalid viewports
    differs though. ddraw1 seems to check for hard zeros, assign some special values,
    and return success. Newer ddraw versions return DDERR_INVALIDPARAMS instead. Setting
    very low values (e. g., 1e-36f) for vp1.dvScaleX still matches between Windows and
    Wine with these patches, setting 0.0f / -0.0f leads to different results (and always
    an error on setting viewport in newer ddraw).

 dlls/ddraw/tests/d3d.c    | 28 ++++++++++++++-----------
 dlls/ddraw/tests/ddraw4.c | 43 +++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/viewport.c     | 13 ++++++------
 3 files changed, 66 insertions(+), 18 deletions(-)

diff --git a/dlls/ddraw/tests/d3d.c b/dlls/ddraw/tests/d3d.c
index e606010a9c..13c925e970 100644
--- a/dlls/ddraw/tests/d3d.c
+++ b/dlls/ddraw/tests/d3d.c
@@ -1050,25 +1050,29 @@ static void ViewportTest(void)
     ret_vp2_data.dwSize = sizeof(vp2_data);
 
     hr = IDirect3DViewport2_GetViewport2(Viewport2, &ret_vp2_data);
-    ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport2 returned %08x\n", hr);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
 
-    ok(ret_vp2_data.dwX == vp1_data.dwX, "dwX is %u, expected %u\n", ret_vp2_data.dwX, vp1_data.dwX);
-    ok(ret_vp2_data.dwY == vp1_data.dwY, "dwY is %u, expected %u\n", ret_vp2_data.dwY, vp1_data.dwY);
-    ok(ret_vp2_data.dwWidth == vp1_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp2_data.dwWidth, vp1_data.dwWidth);
-    ok(ret_vp2_data.dwHeight == vp1_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp2_data.dwHeight, vp1_data.dwHeight);
-    ok(ret_vp2_data.dvClipX == vp2_data.dvClipX, "dvClipX is %f, expected %f\n", ret_vp2_data.dvClipX, vp2_data.dvClipX);
-    ok(ret_vp2_data.dvClipY == vp2_data.dvClipY, "dvClipY is %f, expected %f\n", ret_vp2_data.dvClipY, vp2_data.dvClipY);
-    ok(ret_vp2_data.dvClipWidth == vp2_data.dvClipWidth, "dvClipWidth is %f, expected %f\n",
+    ok(ret_vp2_data.dwX == vp1_data.dwX, "dwX is %u, expected %u.\n", ret_vp2_data.dwX, vp1_data.dwX);
+    ok(ret_vp2_data.dwY == vp1_data.dwY, "dwY is %u, expected %u.\n", ret_vp2_data.dwY, vp1_data.dwY);
+    ok(ret_vp2_data.dwWidth == vp1_data.dwWidth, "dwWidth is %u, expected %u.\n",
+            ret_vp2_data.dwWidth, vp1_data.dwWidth);
+    ok(ret_vp2_data.dwHeight == vp1_data.dwHeight, "dwHeight is %u, expected %u.\n",
+            ret_vp2_data.dwHeight, vp1_data.dwHeight);
+    todo_wine ok(ret_vp2_data.dvClipX == vp2_data.dvClipX, "dvClipX is %f, expected %f.\n",
+            ret_vp2_data.dvClipX, vp2_data.dvClipX);
+    todo_wine ok(ret_vp2_data.dvClipY == vp2_data.dvClipY, "dvClipY is %f, expected %f.\n",
+            ret_vp2_data.dvClipY, vp2_data.dvClipY);
+    todo_wine ok(ret_vp2_data.dvClipWidth == vp2_data.dvClipWidth, "dvClipWidth is %f, expected %f.\n",
         ret_vp2_data.dvClipWidth, vp2_data.dvClipWidth);
-    ok(ret_vp2_data.dvClipHeight == vp2_data.dvClipHeight, "dvClipHeight is %f, expected %f\n",
+    todo_wine ok(ret_vp2_data.dvClipHeight == vp2_data.dvClipHeight, "dvClipHeight is %f, expected %f.\n",
         ret_vp2_data.dvClipHeight, vp2_data.dvClipHeight);
-    ok(ret_vp2_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp2_data.dvMinZ);
-    ok(ret_vp2_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp2_data.dvMaxZ);
+    ok(ret_vp2_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0.\n", ret_vp2_data.dvMinZ);
+    ok(ret_vp2_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0.\n", ret_vp2_data.dvMaxZ);
 
     IDirect3DViewport2_Release(Viewport2);
 
     hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
-    ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
 }
 
 static void Direct3D1Test(void)
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index 114f4b5ed6..8cadfae52a 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -1837,11 +1837,54 @@ static void test_viewport_object(void)
             "Got unexpected values %g, %g, %g, %g, %g, %g.\n",
             vp.dvMaxX, vp.dvMaxY, vp.dvScaleX, vp.dvScaleY, vp.dvMinZ, vp.dvMaxZ);
 
+    vp.dwSize = sizeof(vp);
+    vp.dvMinZ = 0.5f;
+    vp.dvMaxZ = 2.0f;
+    hr = IDirect3DViewport3_SetViewport(viewport3, &vp);
+    ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+    memset(&vp2, 0xff, sizeof(vp2));
+    vp2.dwSize = sizeof(vp2);
+    hr = IDirect3DViewport3_GetViewport2(viewport3, &vp2);
+    ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+    ok(vp2.dvClipX == 0.75f && vp2.dvClipY == 1.0f && vp2.dvClipWidth == -1.5f
+            && vp2.dvClipHeight == 2.0f && vp2.dvMinZ == 0.0f && vp2.dvMaxZ == 1.0f,
+            "Got unexpected values %g, %g, %g, %g, %g, %g.\n",
+            vp2.dvClipX, vp2.dvClipY, vp2.dvClipWidth, vp2.dvClipHeight, vp2.dvMinZ, vp2.dvMaxZ);
+
+    vp.dvMaxX = 4.5f;
+    vp.dvMaxY = -1.75f;
+    vp.dvScaleX = 192.0f;
+    vp.dvScaleY = -240.0f;
+    vp.dvMinZ = 2.0f;
+    vp.dvMaxZ = 0.5f;
+
+    hr = IDirect3DViewport3_SetViewport(viewport3, &vp);
+    ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+
+    memset(&vp2, 0xff, sizeof(vp2));
+    vp2.dwSize = sizeof(vp2);
+    hr = IDirect3DViewport3_GetViewport2(viewport3, &vp2);
+    ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+    ok(vp2.dvClipX == -1.25f && vp2.dvClipY == -0.75f && vp2.dvClipWidth == 2.5f
+            && vp2.dvClipHeight == -1.5f && vp2.dvMinZ == 0.0f && vp2.dvMaxZ == 1.0f,
+            "Got unexpected values %g, %g, %g, %g, %g, %g.\n",
+            vp2.dvClipX, vp2.dvClipY, vp2.dvClipWidth, vp2.dvClipHeight, vp2.dvMinZ, vp2.dvMaxZ);
+
     /* Destroying the device removes the viewport and releases the reference */
     IDirect3DDevice3_Release(device);
     ref = get_refcount((IUnknown *) viewport3);
     ok(ref == 1, "Got unexpected refcount %u.\n", ref);
 
+    memset(&vp2, 0xff, sizeof(vp2));
+    vp2.dwSize = sizeof(vp2);
+    hr = IDirect3DViewport3_GetViewport2(viewport3, &vp2);
+    ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+    ok(vp2.dvClipX == -1.25f && vp2.dvClipY == -0.75f && vp2.dvClipWidth == 2.5f
+            && vp2.dvClipHeight == -1.5f && vp2.dvMinZ == 0.0f && vp2.dvMaxZ == 1.0f,
+            "Got unexpected values %g, %g, %g, %g, %g, %g.\n",
+            vp2.dvClipX, vp2.dvClipY, vp2.dvClipWidth, vp2.dvClipHeight, vp2.dvMinZ, vp2.dvMaxZ);
+
     vp.dwSize = sizeof(vp);
     hr = IDirect3DViewport3_SetViewport(viewport3, &vp);
     ok(hr == D3DERR_VIEWPORTHASNODEVICE, "Got unexpected hr %#x.\n", hr);
diff --git a/dlls/ddraw/viewport.c b/dlls/ddraw/viewport.c
index ceb5582524..0a06329a69 100644
--- a/dlls/ddraw/viewport.c
+++ b/dlls/ddraw/viewport.c
@@ -983,12 +983,13 @@ static HRESULT WINAPI d3d_viewport_GetViewport2(IDirect3DViewport3 *iface, D3DVI
         vp2.dwY = viewport->viewports.vp1.dwY;
         vp2.dwWidth = viewport->viewports.vp1.dwWidth;
         vp2.dwHeight = viewport->viewports.vp1.dwHeight;
-        vp2.dvClipX = 0.0f;
-        vp2.dvClipY = 0.0f;
-        vp2.dvClipWidth = 0.0f;
-        vp2.dvClipHeight = 0.0f;
-        vp2.dvMinZ = viewport->viewports.vp1.dvMinZ;
-        vp2.dvMaxZ = viewport->viewports.vp1.dvMaxZ;
+
+        vp2.dvClipWidth = viewport->viewports.vp1.dwWidth / viewport->viewports.vp1.dvScaleX;
+        vp2.dvClipHeight = viewport->viewports.vp1.dwHeight / viewport->viewports.vp1.dvScaleY;
+        vp2.dvClipX = -vp2.dvClipWidth / 2.0f;
+        vp2.dvClipY = vp2.dvClipHeight / 2.0f;
+        vp2.dvMinZ = 0.0f;
+        vp2.dvMaxZ = 1.0f;
         memcpy(vp, &vp2, size);
     }
 
-- 
2.23.0




More information about the wine-devel mailing list