[PATCH 1/5] ddraw/tests: Move IDirect3DViewport::TransformVertices tests to ddraw1.c (v2).

Stefan Dösinger stefandoesinger at gmx.at
Wed Aug 31 16:01:23 CDT 2016


The immediate problem I wanted to fix is the output array overflow
on Windows. Ports to ddraw2-4 will follow.

Version 2: Fix a trailing whitespace, introduce compare_vec4. I have
kept compare_vec4 equal to the ddraw7 version for consistency, even
though I could make it accept two vec4 pointers for the use case of this
specific test.

Signed-off-by: Stefan Dösinger <stefandoesinger at gmx.at>
---
 dlls/ddraw/tests/d3d.c    | 275 ----------------------------------
 dlls/ddraw/tests/ddraw1.c | 365 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 365 insertions(+), 275 deletions(-)

diff --git a/dlls/ddraw/tests/d3d.c b/dlls/ddraw/tests/d3d.c
index 8c82e4c..b7d3b05 100644
--- a/dlls/ddraw/tests/d3d.c
+++ b/dlls/ddraw/tests/d3d.c
@@ -1112,45 +1112,16 @@ static void ViewportTest(void)
     ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
 }
 
-#define SET_VP_DATA(vp_data) \
-    vp_data.dwSize = sizeof(vp_data); \
-    vp_data.dwX = 0; \
-    vp_data.dwY = 0; \
-    vp_data.dwWidth = 256; \
-    vp_data.dwHeight = 256; \
-    vp_data.dvMaxX = 256; \
-    vp_data.dvMaxY = 256; \
-    vp_data.dvScaleX = 5; \
-    vp_data.dvScaleY = 5; \
-    vp_data.dvMinZ = -25; \
-    vp_data.dvMaxZ = 60;
-
 static void Direct3D1Test(void)
 {
     HRESULT hr;
     D3DEXECUTEBUFFERDESC desc;
-    D3DVIEWPORT vp_data;
     D3DINSTRUCTION *instr;
     D3DBRANCH *branch;
     IDirect3D *Direct3D_alt;
     IDirect3DLight *d3dlight;
     ULONG refcount;
     unsigned int idx = 0;
-    static struct v_in testverts[] = {
-        {0.0, 0.0, 0.0},  { 1.0,  1.0,  1.0}, {-1.0, -1.0, -1.0},
-        {0.5, 0.5, 0.5},  {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
-    };
-    static struct v_in cliptest[] = {
-        {25.59, 25.59, 1.0},  {-25.59, -25.59,  0.0},
-        {25.61, 25.61, 1.01}, {-25.61, -25.61, -0.01},
-    };
-    static struct v_in offscreentest[] = {
-        {128.1, 0.0, 0.0},
-    };
-    struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
-    D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
-    D3DTRANSFORMDATA transformdata;
-    DWORD i = 0;
 
     /* Interface consistency check. */
     hr = IDirect3DDevice_GetDirect3D(Direct3DDevice1, &Direct3D_alt);
@@ -1235,252 +1206,6 @@ static void Direct3D1Test(void)
     hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
     ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
 
-    memset(&transformdata, 0, sizeof(transformdata));
-    transformdata.dwSize = sizeof(transformdata);
-    transformdata.lpIn = testverts;
-    transformdata.dwInSize = sizeof(testverts[0]);
-    transformdata.lpOut = out;
-    transformdata.dwOutSize = sizeof(out[0]);
-
-    transformdata.lpHOut = NULL;
-    hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
-                                             &transformdata, D3DTRANSFORM_UNCLIPPED,
-                                             &i);
-    ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
-
-    for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
-        static const struct v_out cmp[] = {
-            {128.0, 128.0, 0.0, 1}, {129.0, 127.0,  1.0, 1}, {127.0, 129.0, -1, 1},
-            {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5,  0, 1}
-        };
-
-        ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
-           cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
-           "Vertex %d differs. Got %f %f %f %f, expected %f %f %f %f\n", i + 1,
-           out[i].x, out[i].y, out[i].z, out[i].rhw,
-           cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
-    }
-
-    SET_VP_DATA(vp_data);
-    hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
-    ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
-    hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
-                                             &transformdata, D3DTRANSFORM_UNCLIPPED,
-                                             &i);
-    ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
-    ok(i == 0, "Offscreen is %d\n", i);
-
-    for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
-        static const struct v_out cmp[] = {
-            {128.0, 128.0, 0.0, 1}, {133.0, 123.0,  1.0, 1}, {123.0, 133.0, -1, 1},
-            {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5,  0, 1}
-        };
-        ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
-           cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
-           "Vertex %d differs. Got %f %f %f %f, expected %f %f %f %f\n", i + 1,
-           out[i].x, out[i].y, out[i].z, out[i].rhw,
-           cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
-    }
-
-    SET_VP_DATA(vp_data);
-    vp_data.dwX = 10;
-    vp_data.dwY = 20;
-    hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
-    ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
-    hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
-                                             &transformdata, D3DTRANSFORM_UNCLIPPED,
-                                             &i);
-    ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
-    ok(i == 0, "Offscreen is %d\n", i);
-    for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
-        static const struct v_out cmp[] = {
-            {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, {133.0, 153.0, -1, 1},
-            {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5,  0, 1}
-        };
-        ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
-           cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
-           "Vertex %d differs. Got %f %f %f %f, expected %f %f %f %f\n", i + 1,
-           out[i].x, out[i].y, out[i].z, out[i].rhw,
-           cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
-    }
-
-    transformdata.lpHOut = outH;
-    memset(out, 0xcc, sizeof(out));
-    hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
-                                             &transformdata, D3DTRANSFORM_CLIPPED,
-                                             &i);
-    ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
-    ok(i == 0, "Offscreen is %d\n", i);
-    for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
-        static const D3DHVERTEX cmpH[] = {
-            {0,             { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
-            {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
-            {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
-        };
-        ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
-           U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
-           "HVertex %d differs. Got %08x %f %f %f, expected %08x %f %f %f\n", i + 1,
-           outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
-           cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
-
-        /* No scheme has been found behind those return values. It seems to be
-         * whatever data windows has when throwing the vertex away. Modify the
-         * input test vertices to test this more. Depending on the input data
-         * it can happen that the z coord gets written into y, or similar things
-         */
-        if(0)
-        {
-            static const struct v_out cmp[] = {
-                {138.0, 148.0, 0.0, 1}, {143.0, 143.0,  1.0, 1}, { -1.0,  -1.0, 0.5, 1},
-                {140.5, 145.5, 0.5, 1}, { -0.5,  -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
-            };
-            ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
-               cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
-                "Vertex %d differs. Got %f %f %f %f, expected %f %f %f %f\n", i + 1,
-               out[i].x, out[i].y, out[i].z, out[i].rhw,
-               cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
-        }
-    }
-    for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
-        ok(((DWORD *) out)[i] != 0xcccccccc,
-                "Regular output DWORD %d remained untouched\n", i);
-    }
-
-    transformdata.lpIn = cliptest;
-    transformdata.dwInSize = sizeof(cliptest[0]);
-    hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
-                                             &transformdata, D3DTRANSFORM_CLIPPED,
-                                             &i);
-    ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
-    ok(i == 0, "Offscreen is %d\n", i);
-    for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
-        DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
-        {
-            0,
-            0,
-            D3DCLIP_RIGHT | D3DCLIP_BACK   | D3DCLIP_TOP,
-            D3DCLIP_LEFT  | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
-        };
-        ok(Flags[i] == outH[i].dwFlags,
-           "Cliptest %d differs. Got %08x expected %08x\n", i + 1,
-           outH[i].dwFlags, Flags[i]);
-    }
-
-    SET_VP_DATA(vp_data);
-    vp_data.dwWidth = 10;
-    vp_data.dwHeight = 1000;
-    hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
-    i = 10;
-    ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
-    hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
-                                             &transformdata, D3DTRANSFORM_CLIPPED,
-                                             &i);
-    ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
-    ok(i == 0, "Offscreen is %d\n", i);
-    for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
-        DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
-        {
-            D3DCLIP_RIGHT,
-            D3DCLIP_LEFT,
-            D3DCLIP_RIGHT | D3DCLIP_BACK,
-            D3DCLIP_LEFT  | D3DCLIP_FRONT,
-        };
-        ok(Flags[i] == outH[i].dwFlags,
-           "Cliptest %d differs. Got %08x expected %08x\n", i + 1,
-           outH[i].dwFlags, Flags[i]);
-    }
-
-    SET_VP_DATA(vp_data);
-    vp_data.dwWidth = 256;
-    vp_data.dwHeight = 256;
-    vp_data.dvScaleX = 1;
-    vp_data.dvScaleY = 1;
-    hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
-    ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
-    hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
-                                             &transformdata, D3DTRANSFORM_CLIPPED,
-                                             &i);
-    ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
-    ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
-    for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
-        DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
-        {
-            0,
-            0,
-            D3DCLIP_BACK,
-            D3DCLIP_FRONT,
-        };
-        ok(Flags[i] == outH[i].dwFlags,
-           "Cliptest %d differs. Got %08x expected %08x\n", i + 1,
-           outH[i].dwFlags, Flags[i]);
-    }
-
-    /* Finally try to figure out how the DWORD dwOffscreen works.
-     * Apparently no vertex is offscreen with clipping off,
-     * and with clipping on the offscreen flag is set if only one vertex
-     * is transformed, and this vertex is offscreen.
-     */
-    SET_VP_DATA(vp_data);
-    vp_data.dwWidth = 5;
-    vp_data.dwHeight = 5;
-    vp_data.dvScaleX = 10000;
-    vp_data.dvScaleY = 10000;
-    hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
-    ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
-    transformdata.lpIn = cliptest;
-    hr = IDirect3DViewport_TransformVertices(Viewport, 1,
-                                             &transformdata, D3DTRANSFORM_UNCLIPPED,
-                                             &i);
-    ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
-    ok(i == 0, "Offscreen is %d\n", i);
-    hr = IDirect3DViewport_TransformVertices(Viewport, 1,
-                                             &transformdata, D3DTRANSFORM_CLIPPED,
-                                             &i);
-    ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
-    ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
-    hr = IDirect3DViewport_TransformVertices(Viewport, 2,
-                                             &transformdata, D3DTRANSFORM_CLIPPED,
-                                             &i);
-    ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
-    ok(i == 0, "Offscreen is %d\n", i);
-    transformdata.lpIn = cliptest + 1;
-    hr = IDirect3DViewport_TransformVertices(Viewport, 1,
-                                             &transformdata, D3DTRANSFORM_CLIPPED,
-                                             &i);
-    ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
-    ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
-
-    transformdata.lpIn = offscreentest;
-    transformdata.dwInSize = sizeof(offscreentest[0]);
-    SET_VP_DATA(vp_data);
-    vp_data.dwWidth = 257;
-    vp_data.dwHeight = 257;
-    vp_data.dvScaleX = 1;
-    vp_data.dvScaleY = 1;
-    hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
-    ok(SUCCEEDED(hr), "IDirect3DViewport_SetViewport returned %#x.\n", hr);
-    i = 12345;
-    hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
-                                             &transformdata, D3DTRANSFORM_CLIPPED,
-                                             &i);
-    ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
-    ok(i == 0, "Offscreen is %d\n", i);
-    vp_data.dwWidth = 256;
-    vp_data.dwHeight = 256;
-    hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
-    ok(SUCCEEDED(hr), "IDirect3DViewport_SetViewport returned %#x.\n", hr);
-    i = 12345;
-    hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
-                                             &transformdata, D3DTRANSFORM_CLIPPED,
-                                             &i);
-    ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
-    ok(i == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
-
-    hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
-                                             &transformdata, 0,
-                                             &i);
-    ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
-
     hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
     ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
 
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index bfc6bfe..cd2d791 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -20,6 +20,7 @@
 #define COBJMACROS
 
 #include "wine/test.h"
+#include <limits.h>
 #include "d3d.h"
 
 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
@@ -27,6 +28,15 @@ static DEVMODEW registry_mode;
 
 static HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *);
 
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+#endif
+
+struct vec4
+{
+    float x, y, z, w;
+};
+
 struct create_window_thread_param
 {
     HWND window;
@@ -47,6 +57,30 @@ static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
     return TRUE;
 }
 
+static BOOL compare_float(float f, float g, unsigned int ulps)
+{
+    int x = *(int *)&f;
+    int y = *(int *)&g;
+
+    if (x < 0)
+        x = INT_MIN - x;
+    if (y < 0)
+        y = INT_MIN - y;
+
+    if (abs(x - y) > ulps)
+        return FALSE;
+
+    return TRUE;
+}
+
+static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
+{
+    return compare_float(vec->x, x, ulps)
+            && compare_float(vec->y, y, ulps)
+            && compare_float(vec->z, z, ulps)
+            && compare_float(vec->w, w, ulps);
+}
+
 static IDirectDrawSurface *create_overlay(IDirectDraw *ddraw,
         unsigned int width, unsigned int height, DWORD format)
 {
@@ -9071,6 +9105,336 @@ static void test_getdc(void)
     DestroyWindow(window);
 }
 
+/* TransformVertices always writes 32 bytes regardless of the input / output stride.
+ * The stride is honored for navigating to the next vertex. 3 floats input position
+ * are read, and 16 bytes extra vertex data are copied around. */
+struct transform_input
+{
+    float x, y, z, unused1; /* Position data, transformed. */
+    DWORD v1, v2, v3, v4; /* Extra data, e.g. color and texture coords, copied. */
+    DWORD unused2;
+};
+
+struct transform_output
+{
+    float x, y, z, w;
+    DWORD v1, v2, v3, v4;
+    DWORD unused3, unused4;
+};
+
+static void test_transform_vertices(void)
+{
+    IDirect3DDevice *device;
+    IDirectDraw *ddraw;
+    ULONG refcount;
+    HWND window;
+    HRESULT hr;
+    IDirect3DViewport *viewport;
+    static struct transform_input position_tests[] =
+    {
+        { 0.0f,  0.0f,  0.0f, 0.0f,   1,   2,   3,   4,   5},
+        { 1.0f,  1.0f,  1.0f, 8.0f,   6,   7,   8,   9,  10},
+        {-1.0f, -1.0f, -1.0f, 4.0f,  11,  12,  13,  14,  15},
+        { 0.5f,  0.5f,  0.5f, 2.0f,  16,  17,  18,  19,  20},
+        {-0.5f, -0.5f, -0.5f, 1.0f, ~1U, ~2U, ~3U, ~4U, ~5U},
+        {-0.5f, -0.5f,  0.0f, 0.0f, ~6U, ~7U, ~8U, ~9U, ~0U},
+    };
+    static struct transform_input cliptest[] =
+    {
+        { 25.59f,  25.59f,  1.0f,  0.0f, 1, 2, 3, 4, 5},
+        { 25.61f,  25.61f,  1.01f, 0.0f, 1, 2, 3, 4, 5},
+        {-25.59f, -25.59f,  0.0f,  0.0f, 1, 2, 3, 4, 5},
+        {-25.61f, -25.61f, -0.01f, 0.0f, 1, 2, 3, 4, 5},
+    };
+    static struct transform_input offscreentest[] =
+    {
+        {128.1f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
+    };
+    struct transform_output out[ARRAY_SIZE(position_tests)];
+    D3DHVERTEX out_h[ARRAY_SIZE(position_tests)];
+    D3DTRANSFORMDATA transformdata;
+    static const D3DVIEWPORT vp_template =
+    {
+        sizeof(vp_template), 0, 0, 256, 256, 5.0f, 5.0f, 256.0f, 256.0f, -25.0f, 60.0f
+    };
+    D3DVIEWPORT vp_data =
+    {
+        sizeof(vp_data), 0, 0, 256, 256, 1.0f, 1.0f, 256.0f, 256.0f, 0.0f, 1.0f
+    };
+    unsigned int i;
+    DWORD offscreen;
+
+    for (i = 0; i < ARRAY_SIZE(out); ++i)
+    {
+        out[i].unused3 = 0xdeadbeef;
+        out[i].unused4 = 0xcafecafe;
+    }
+
+    window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+            0, 0, 640, 480, 0, 0, 0, 0);
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+    if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
+    {
+        skip("Failed to create a 3D device, skipping test.\n");
+        IDirectDraw_Release(ddraw);
+        DestroyWindow(window);
+        return;
+    }
+
+    viewport = create_viewport(device, 0, 0, 256, 256);
+    hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
+    ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
+
+    memset(&transformdata, 0, sizeof(transformdata));
+    transformdata.dwSize = sizeof(transformdata);
+    transformdata.lpIn = position_tests;
+    transformdata.dwInSize = sizeof(position_tests[0]);
+    transformdata.lpOut = out;
+    transformdata.dwOutSize = sizeof(out[0]);
+    transformdata.lpHOut = NULL;
+
+    hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
+            &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
+    ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
+    ok(!offscreen, "Offscreen is %x.\n", offscreen);
+
+    for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
+    {
+        static const struct vec4 cmp[] =
+        {
+            {128.0f, 128.0f, 0.0f, 1.0f}, {129.0f, 127.0f,  1.0f, 1.0f}, {127.0f, 129.0f, -1.0f, 1.0f},
+            {128.5f, 127.5f, 0.5f, 1.0f}, {127.5f, 128.5f, -0.5f, 1.0f}, {127.5f, 128.5f,  0.0f, 1.0f}
+        };
+
+        ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
+                "Vertex %u differs. Got %f %f %f %f.\n", i,
+                out[i].x, out[i].y, out[i].z, out[i].w);
+        todo_wine ok(out[i].v1 == position_tests[i].v1 && out[i].v2 == position_tests[i].v2
+                && out[i].v3 == position_tests[i].v3 && out[i].v4 == position_tests[i].v4,
+                "Vertex %u payload is %u %u %u %u.\n", i, out[i].v1, out[i].v2, out[i].v3, out[i].v4);
+        ok(out[i].unused3 == 0xdeadbeef && out[i].unused4 == 0xcafecafe,
+                "Vertex %u unused data is %#x, %#x.\n", i, out[i].unused3, out[i].unused4);
+    }
+
+    vp_data = vp_template;
+    hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
+    ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
+    offscreen = 0xdeadbeef;
+    hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
+            &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
+    ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
+    ok(!offscreen, "Offscreen is %x.\n", offscreen);
+
+    for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
+    {
+        static const struct vec4 cmp[] =
+        {
+            {128.0f, 128.0f, 0.0f, 1.0f}, {133.0f, 123.0f,  1.0f, 1.0f}, {123.0f, 133.0f, -1.0f, 1.0f},
+            {130.5f, 125.5f, 0.5f, 1.0f}, {125.5f, 130.5f, -0.5f, 1.0f}, {125.5f, 130.5f,  0.0f, 1.0f}
+        };
+        ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
+                "Vertex %u differs. Got %f %f %f %f.\n", i,
+                out[i].x, out[i].y, out[i].z, out[i].w);
+    }
+
+    vp_data.dwX = 10;
+    vp_data.dwY = 20;
+    hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
+    ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
+    offscreen = 0xdeadbeef;
+    hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
+            &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
+    ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
+    ok(!offscreen, "Offscreen is %x.\n", offscreen);
+    for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
+    {
+        static const struct vec4 cmp[] =
+        {
+            {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f,  1.0f, 1.0f}, {133.0f, 153.0f, -1.0f, 1.0f},
+            {140.5f, 145.5f, 0.5f, 1.0f}, {135.5f, 150.5f, -0.5f, 1.0f}, {135.5f, 150.5f,  0.0f, 1.0f}
+        };
+        ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
+                "Vertex %u differs. Got %f %f %f %f.\n", i,
+                out[i].x, out[i].y, out[i].z, out[i].w);
+    }
+
+    transformdata.lpHOut = out_h;
+    offscreen = 0xdeadbeef;
+    hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
+            &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
+    ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
+    ok(!offscreen, "Offscreen is %x.\n", offscreen);
+    for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
+    {
+        static const D3DHVERTEX cmp_h[] =
+        {
+            {0,             { 0.0f}, { 0.0f}, { 0.0f}}, {0, { 1.0f}, { 1.0f}, {1.0f}},
+            {D3DCLIP_FRONT, {-1.0f}, {-1.0f}, {-1.0f}}, {0, { 0.5f}, { 0.5f}, {0.5f}},
+            {D3DCLIP_FRONT, {-0.5f}, {-0.5f}, {-0.5f}}, {0, {-0.5f}, {-0.5f}, {0.0f}}
+        };
+        ok(compare_float(U1(cmp_h[i]).hx, U1(out_h[i]).hx, 4096)
+                && compare_float(U1(cmp_h[i]).hy, U1(out_h[i]).hy, 4096)
+                && compare_float(U1(cmp_h[i]).hz, U1(out_h[i]).hz, 4096)
+                && cmp_h[i].dwFlags == out_h[i].dwFlags,
+                "HVertex %u differs. Got %#x %f %f %f.\n", i,
+                out_h[i].dwFlags, U1(out_h[i]).hx, U2(out_h[i]).hy, U3(out_h[i]).hz);
+
+        /* No scheme has been found behind those return values. It seems to be
+         * whatever data windows has when throwing the vertex away. Modify the
+         * input test vertices to test this more. Depending on the input data
+         * it can happen that the z coord gets written into y, or similar things. */
+        if (0)
+        {
+            static const struct vec4 cmp[] =
+            {
+                {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f,  1.0f, 1.0f}, { -1.0f,  -1.0f, 0.5f, 1.0f},
+                {140.5f, 145.5f, 0.5f, 1.0f}, { -0.5f,  -0.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
+            };
+            ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
+                    "Vertex %u differs. Got %f %f %f %f.\n", i,
+                    out[i].x, out[i].y, out[i].z, out[i].w);
+        }
+    }
+
+    transformdata.lpIn = cliptest;
+    transformdata.dwInSize = sizeof(cliptest[0]);
+    offscreen = 0xdeadbeef;
+    hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(cliptest),
+            &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
+    ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
+    ok(!offscreen, "Offscreen is %x.\n", offscreen);
+    for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
+    {
+        static const DWORD flags[] =
+        {
+            0,
+            D3DCLIP_RIGHT | D3DCLIP_BACK   | D3DCLIP_TOP,
+            0,
+            D3DCLIP_LEFT  | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
+        };
+        ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
+    }
+
+    vp_data = vp_template;
+    vp_data.dwWidth = 10;
+    vp_data.dwHeight = 1000;
+    hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
+    ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
+    offscreen = 0xdeadbeef;
+    hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(cliptest),
+            &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
+    ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
+    ok(!offscreen, "Offscreen is %x.\n", offscreen);
+    for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
+    {
+        static const DWORD flags[] =
+        {
+            D3DCLIP_RIGHT,
+            D3DCLIP_RIGHT | D3DCLIP_BACK,
+            D3DCLIP_LEFT,
+            D3DCLIP_LEFT  | D3DCLIP_FRONT,
+        };
+        ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
+    }
+
+    vp_data = vp_template;
+    vp_data.dwWidth = 256;
+    vp_data.dwHeight = 256;
+    vp_data.dvScaleX = 1;
+    vp_data.dvScaleY = 1;
+    hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
+    ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
+    hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(cliptest),
+            &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
+    ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
+    ok(!offscreen, "Offscreen is %x.\n", offscreen);
+    for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
+    {
+        static const DWORD flags[] =
+        {
+            0,
+            D3DCLIP_BACK,
+            0,
+            D3DCLIP_FRONT,
+        };
+        ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
+    }
+
+    /* Finally try to figure out how the DWORD dwOffscreen works.
+     * Apparently no vertex is offscreen with clipping off,
+     * and with clipping on the offscreen flag is set if only one vertex
+     * is transformed, and this vertex is offscreen.
+     *
+     * FIXME: This is wrong. It might be the logical AND of all
+     * output clip flags. */
+    vp_data = vp_template;
+    vp_data.dwWidth = 5;
+    vp_data.dwHeight = 5;
+    vp_data.dvScaleX = 10000.0f;
+    vp_data.dvScaleY = 10000.0f;
+    hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
+    ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
+    transformdata.lpIn = cliptest;
+    offscreen = 0xdeadbeef;
+    hr = IDirect3DViewport_TransformVertices(viewport, 1,
+            &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
+    ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
+    ok(!offscreen, "Offscreen is %x.\n", offscreen);
+
+    offscreen = 0xdeadbeef;
+    hr = IDirect3DViewport_TransformVertices(viewport, 1,
+            &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
+    ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
+    ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
+
+    hr = IDirect3DViewport_TransformVertices(viewport, 2,
+            &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
+    ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
+    todo_wine ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
+
+    transformdata.lpIn = cliptest + 2;
+    hr = IDirect3DViewport_TransformVertices(viewport, 1,
+            &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
+    ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
+    ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
+
+    transformdata.lpIn = offscreentest;
+    transformdata.dwInSize = sizeof(offscreentest[0]);
+    vp_data = vp_template;
+    vp_data.dwWidth = 257;
+    vp_data.dwHeight = 257;
+    vp_data.dvScaleX = 1.0f;
+    vp_data.dvScaleY = 1.0f;
+    hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
+    ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
+    offscreen = 0xdeadbeef;
+    hr = IDirect3DViewport_TransformVertices(viewport, 1,
+            &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
+    ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
+    ok(!offscreen, "Offscreen is %x.\n", offscreen);
+
+    vp_data.dwWidth = 256;
+    vp_data.dwHeight = 256;
+    hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
+    ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
+    hr = IDirect3DViewport_TransformVertices(viewport, 1,
+            &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
+    ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
+    ok(offscreen == D3DCLIP_RIGHT, "Offscreen is %x.\n", offscreen);
+
+    /* Invalid flags. */
+    hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
+            &transformdata, 0, &offscreen);
+    ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
+
+    destroy_viewport(device, viewport);
+    refcount = IDirect3DDevice_Release(device);
+    ok(!refcount, "Device has %u references left.\n", refcount);
+    IDirectDraw_Release(ddraw);
+    DestroyWindow(window);
+}
+
 START_TEST(ddraw1)
 {
     IDirectDraw *ddraw;
@@ -9153,4 +9517,5 @@ START_TEST(ddraw1)
     test_overlay_rect();
     test_blt();
     test_getdc();
+    test_transform_vertices();
 }
-- 
2.7.3




More information about the wine-patches mailing list