[PATCH 8/8] ddraw/tests: Add viewport handling tests
Stefan Dösinger
stefan at codeweavers.com
Sat Jan 26 06:39:49 CST 2013
I did not implement the IDirect3DDevice2 reference leaking behavior,
although it is striking that the behavior is the same on win7 and winxp.
---
dlls/ddraw/tests/ddraw1.c | 51 +++++++++++++++----
dlls/ddraw/tests/ddraw2.c | 109 ++++++++++++++++++++++++++++++++++++++--
dlls/ddraw/tests/ddraw4.c | 123 ++++++++++++++++++++++++++++++++++++++++------
3 files changed, 256 insertions(+), 27 deletions(-)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index 80121f0..d3a296c 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -935,32 +935,38 @@ static ULONG get_refcount(IUnknown *test_iface)
return IUnknown_Release(test_iface);
}
-static void test_viewport_interfaces(void)
+static void test_viewport(void)
{
IDirectDraw *ddraw;
IDirect3D *d3d;
HRESULT hr;
ULONG ref;
- IDirect3DViewport *viewport;
+ IDirect3DViewport *viewport, *another_vp;
IDirect3DViewport2 *viewport2;
IDirect3DViewport3 *viewport3;
IDirectDrawGammaControl *gamma;
IUnknown *unknown;
+ IDirect3DDevice *device;
+ HWND window;
if (!(ddraw = create_ddraw()))
{
skip("Failed to create ddraw object, skipping test.\n");
return;
}
- hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
- ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get d3d interface, hr %#x.\n", hr);
- if (FAILED(hr))
+ window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+ 0, 0, 640, 480, 0, 0, 0, 0);
+ if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
{
- skip("Direct3D not available, skipping tests\n");
+ skip("Failed to create D3D device, skipping test.\n");
IDirectDraw_Release(ddraw);
+ DestroyWindow(window);
return;
}
- ref = get_refcount((IUnknown *)d3d);
+
+ hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
+ ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) d3d);
ok(ref == 2, "IDirect3D refcount is %d\n", ref);
hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
@@ -1016,8 +1022,35 @@ static void test_viewport_interfaces(void)
IUnknown_Release(unknown);
}
- IDirect3DViewport_Release(viewport);
+ /* AddViewport(NULL): Segfault */
+ hr = IDirect3DDevice_DeleteViewport(device, NULL);
+ ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3D_CreateViewport(d3d, &another_vp, NULL);
+ ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
+
+ hr = IDirect3DDevice_AddViewport(device, viewport);
+ ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) viewport);
+ ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
+ hr = IDirect3DDevice_AddViewport(device, another_vp);
+ ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) another_vp);
+ ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
+
+ hr = IDirect3DDevice_DeleteViewport(device, another_vp);
+ ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) another_vp);
+ ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
+
+ IDirect3DDevice_Release(device);
+ ref = get_refcount((IUnknown *) viewport);
+ ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
+
+ IDirect3DViewport_Release(another_vp);
IDirect3D_Release(d3d);
+ IDirect3DViewport_Release(viewport);
+ DestroyWindow(window);
IDirectDraw_Release(ddraw);
}
@@ -2731,7 +2764,7 @@ START_TEST(ddraw1)
test_coop_level_d3d_state();
test_surface_interface_mismatch();
test_coop_level_threaded();
- test_viewport_interfaces();
+ test_viewport();
test_zenable();
test_ck_rgba();
test_ck_default();
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index a3ecbfd..a52cb78 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -1179,23 +1179,34 @@ static ULONG get_refcount(IUnknown *test_iface)
return IUnknown_Release(test_iface);
}
-static void test_viewport_interfaces(void)
+static void test_viewport(void)
{
IDirectDraw2 *ddraw;
IDirect3D2 *d3d;
HRESULT hr;
ULONG ref, old_d3d_ref;
IDirect3DViewport *viewport;
- IDirect3DViewport2 *viewport2;
+ IDirect3DViewport2 *viewport2, *another_vp, *test_vp;
IDirect3DViewport3 *viewport3;
IDirectDrawGammaControl *gamma;
IUnknown *unknown;
+ IDirect3DDevice2 *device;
+ HWND window;
if (!(ddraw = create_ddraw()))
{
skip("Failed to create ddraw object, skipping test.\n");
return;
}
+ window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+ 0, 0, 640, 480, 0, 0, 0, 0);
+ if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
+ {
+ skip("Failed to create D3D device, skipping test.\n");
+ IDirectDraw_Release(ddraw);
+ DestroyWindow(window);
+ return;
+ }
hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get d3d interface, hr %#x.\n", hr);
@@ -1255,8 +1266,100 @@ static void test_viewport_interfaces(void)
IUnknown_Release(unknown);
}
+ /* AddViewport(NULL): Segfault */
+ hr = IDirect3DDevice2_DeleteViewport(device, NULL);
+ ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice2_GetCurrentViewport(device, NULL);
+ ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3D2_CreateViewport(d3d, &another_vp, NULL);
+ ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
+
+ /* Setting a viewport not in the viewport list fails */
+ hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
+ ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice2_AddViewport(device, viewport2);
+ ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) viewport2);
+ ok(ref == 2, "viewport2 refcount is %d\n", ref);
+ hr = IDirect3DDevice2_AddViewport(device, another_vp);
+ ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) another_vp);
+ ok(ref == 2, "another_vp refcount is %d\n", ref);
+
+ test_vp = (IDirect3DViewport2 *) 0xbaadc0de;
+ hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
+ ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
+ ok(test_vp == (IDirect3DViewport2 *) 0xbaadc0de, "Got unexpected pointer %p\n", test_vp);
+
+ hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
+ ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) viewport2);
+ ok(ref == 3, "viewport2 refcount is %d\n", ref);
+ ref = get_refcount((IUnknown *) device);
+ ok(ref == 1, "device refcount is %d\n", ref);
+
+ test_vp = NULL;
+ hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
+ ref = get_refcount((IUnknown *) viewport2);
+ ok(ref == 4, "viewport2 refcount is %d\n", ref);
+ if(test_vp) IDirect3DViewport2_Release(test_vp);
+
+ /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
+
+ /* Cannot set the viewport to NULL */
+ hr = IDirect3DDevice2_SetCurrentViewport(device, NULL);
+ ok(hr == DDERR_INVALIDPARAMS, "Failed to set viewport to NULL, hr %#x.\n", hr);
+ test_vp = NULL;
+ hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
+ if(test_vp) IDirect3DViewport2_Release(test_vp);
+
+ /* SetCurrentViewport properly releases the old viewport's reference */
+ hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
+ ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) viewport2);
+ ok(ref == 2, "viewport2 refcount is %d\n", ref);
+ ref = get_refcount((IUnknown *) another_vp);
+ ok(ref == 3, "another_vp refcount is %d\n", ref);
+
+ /* Deleting the viewport removes the reference added by AddViewport, but not
+ * the one added by SetCurrentViewport. */
+ hr = IDirect3DDevice2_DeleteViewport(device, another_vp);
+ ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) another_vp);
+ todo_wine ok(ref == 2, "IDirect3DViewport2 refcount is %d\n", ref);
+
+ /* GetCurrentViewport fails though */
+ test_vp = NULL;
+ hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
+ ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
+ ok(test_vp == NULL, "Got unexpected viewport %p\n", test_vp);
+ if(test_vp) IDirect3DViewport2_Release(test_vp);
+
+ /* Setting a different viewport does not free the leaked reference. How
+ * do I get rid of it? Leak the viewport for now. */
+ hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
+ ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) viewport2);
+ ok(ref == 3, "viewport2 refcount is %d\n", ref);
+ ref = get_refcount((IUnknown *) another_vp);
+ todo_wine ok(ref == 2, "another_vp refcount is %d\n", ref);
+
+ /* Destroying the device removes the viewport, but does not free the reference
+ * added by SetCurrentViewport. */
+ IDirect3DDevice2_Release(device);
+ ref = get_refcount((IUnknown *) viewport2);
+ todo_wine ok(ref == 2, "viewport2 refcount is %d\n", ref);
+
+ IDirect3DViewport2_Release(another_vp);
IDirect3DViewport2_Release(viewport2);
IDirect3D2_Release(d3d);
+ DestroyWindow(window);
IDirectDraw2_Release(ddraw);
}
@@ -2855,7 +2958,7 @@ START_TEST(ddraw2)
test_coop_level_threaded();
test_depth_blit();
test_texture_load_ckey();
- test_viewport_interfaces();
+ test_viewport();
test_zenable();
test_ck_rgba();
test_ck_default();
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index e43143f..55b6c01 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -1328,7 +1328,7 @@ static ULONG get_refcount(IUnknown *test_iface)
return IUnknown_Release(test_iface);
}
-static void test_viewport_interfaces(void)
+static void test_viewport(void)
{
IDirectDraw4 *ddraw;
IDirect3D3 *d3d;
@@ -1336,24 +1336,25 @@ static void test_viewport_interfaces(void)
ULONG ref;
IDirect3DViewport *viewport;
IDirect3DViewport2 *viewport2;
- IDirect3DViewport3 *viewport3;
+ IDirect3DViewport3 *viewport3, *another_vp, *test_vp;
IDirectDrawGammaControl *gamma;
IUnknown *unknown;
+ HWND window;
+ IDirect3DDevice3 *device;
- if (!(ddraw = create_ddraw()))
- {
- skip("Failed to create ddraw object, skipping test.\n");
- return;
- }
- hr = IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d);
- ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get d3d interface, hr %#x.\n", hr);
- if (FAILED(hr))
+ window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+ 0, 0, 640, 480, 0, 0, 0, 0);
+ if (!(device = create_device(window, DDSCL_NORMAL)))
{
- skip("Direct3D not available, skipping tests\n");
- IDirectDraw4_Release(ddraw);
+ skip("Failed to create D3D device, skipping test.\n");
+ DestroyWindow(window);
return;
}
- old_d3d_ref = get_refcount((IUnknown *)d3d);
+ hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
+ ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
+ hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
+ ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
+ old_d3d_ref = get_refcount((IUnknown *) d3d);
hr = IDirect3D3_CreateViewport(d3d, &viewport3, NULL);
ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
@@ -1403,8 +1404,100 @@ static void test_viewport_interfaces(void)
IUnknown_Release(unknown);
}
- IDirect3DViewport3_Release(viewport3);
+ /* AddViewport(NULL): Segfault */
+ hr = IDirect3DDevice3_DeleteViewport(device, NULL);
+ ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice3_GetCurrentViewport(device, NULL);
+ ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3D3_CreateViewport(d3d, &another_vp, NULL);
+ ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
+
+ /* Setting a viewport not in the viewport list fails */
+ hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
+ ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice3_AddViewport(device, viewport3);
+ ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) viewport3);
+ ok(ref == 2, "viewport3 refcount is %d\n", ref);
+ hr = IDirect3DDevice3_AddViewport(device, another_vp);
+ ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) another_vp);
+ ok(ref == 2, "another_vp refcount is %d\n", ref);
+
+ test_vp = (IDirect3DViewport3 *) 0xbaadc0de;
+ hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
+ ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
+ ok(test_vp == (IDirect3DViewport3 *) 0xbaadc0de, "Got unexpected pointer %p\n", test_vp);
+
+ hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
+ ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) viewport3);
+ ok(ref == 3, "viewport3 refcount is %d\n", ref);
+ ref = get_refcount((IUnknown *) device);
+ ok(ref == 1, "device refcount is %d\n", ref);
+
+ test_vp = NULL;
+ hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ ok(test_vp == viewport3, "Got unexpected viewport %p\n", test_vp);
+ ref = get_refcount((IUnknown *) viewport3);
+ ok(ref == 4, "viewport3 refcount is %d\n", ref);
+ if(test_vp) IDirect3DViewport3_Release(test_vp);
+
+ /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
+
+ /* Cannot set the viewport to NULL */
+ hr = IDirect3DDevice3_SetCurrentViewport(device, NULL);
+ ok(hr == DDERR_INVALIDPARAMS, "Failed to set viewport to NULL, hr %#x.\n", hr);
+ test_vp = NULL;
+ hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ ok(test_vp == viewport3, "Got unexpected viewport %p\n", test_vp);
+ if(test_vp) IDirect3DViewport3_Release(test_vp);
+
+ /* SetCurrentViewport properly releases the old viewport's reference */
+ hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
+ ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) viewport3);
+ ok(ref == 2, "viewport3 refcount is %d\n", ref);
+ ref = get_refcount((IUnknown *) another_vp);
+ ok(ref == 3, "another_vp refcount is %d\n", ref);
+
+ /* Unlike device2::DeleteViewport, device3::DeleteViewport releases the
+ * reference held by SetCurrentViewport */
+ hr = IDirect3DDevice3_DeleteViewport(device, another_vp);
+ ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) another_vp);
+ ok(ref == 1, "another_vp refcount is %d\n", ref);
+
+ /* GetCurrentViewport still fails */
+ test_vp = NULL;
+ hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
+ ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
+ ok(test_vp == NULL, "Got unexpected viewport %p\n", test_vp);
+ if(test_vp) IDirect3DViewport3_Release(test_vp);
+
+ /* Setting a different viewport doesn't have any surprises now */
+ hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
+ ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
+ ref = get_refcount((IUnknown *) viewport3);
+ ok(ref == 3, "viewport3 refcount is %d\n", ref);
+ ref = get_refcount((IUnknown *) another_vp);
+ ok(ref == 1, "another_vp refcount is %d\n", ref);
+
+ /* Destroying the device removes the viewport and releases the reference */
+ IDirect3DDevice3_Release(device);
+ ref = get_refcount((IUnknown *) viewport3);
+ ok(ref == 1, "viewport3 refcount is %d\n", ref);
+
+ ref = IDirect3DViewport3_Release(another_vp);
+ ok(ref == 0, "Got unexpected ref %d\n", ref);
+ ref = IDirect3DViewport3_Release(viewport3);
+ ok(ref == 0, "Got unexpected ref %d\n", ref);
IDirect3D3_Release(d3d);
+ DestroyWindow(window);
IDirectDraw4_Release(ddraw);
}
@@ -3090,7 +3183,7 @@ START_TEST(ddraw4)
test_coop_level_threaded();
test_depth_blit();
test_texture_load_ckey();
- test_viewport_interfaces();
+ test_viewport();
test_zenable();
test_ck_rgba();
test_ck_default();
--
1.7.12.4
More information about the wine-patches
mailing list