ddraw: SetSurfaceDesc does not work on primaries.
[wine.git] / dlls / ddraw / tests / ddraw4.c
blobfb9f8fe534cef441290b58da86fe0b8e188c10e4
1 /*
2 * Copyright 2011-2012 Henri Verbeet for CodeWeavers
3 * Copyright 2012-2013 Stefan Dösinger for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include "wine/test.h"
22 #include <limits.h>
23 #include "d3d.h"
25 struct vec2
27 float x, y;
30 struct vec3
32 float x, y, z;
35 struct vec4
37 float x, y, z, w;
40 struct create_window_thread_param
42 HWND window;
43 HANDLE window_created;
44 HANDLE destroy_window;
45 HANDLE thread;
48 static BOOL compare_float(float f, float g, unsigned int ulps)
50 int x = *(int *)&f;
51 int y = *(int *)&g;
53 if (x < 0)
54 x = INT_MIN - x;
55 if (y < 0)
56 y = INT_MIN - y;
58 if (abs(x - y) > ulps)
59 return FALSE;
61 return TRUE;
64 static BOOL compare_vec4(struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
66 return compare_float(vec->x, x, ulps)
67 && compare_float(vec->y, y, ulps)
68 && compare_float(vec->z, z, ulps)
69 && compare_float(vec->w, w, ulps);
72 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
74 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
75 c1 >>= 8; c2 >>= 8;
76 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
77 c1 >>= 8; c2 >>= 8;
78 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
79 c1 >>= 8; c2 >>= 8;
80 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
81 return TRUE;
84 static DWORD WINAPI create_window_thread_proc(void *param)
86 struct create_window_thread_param *p = param;
87 DWORD res;
88 BOOL ret;
90 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
91 0, 0, 640, 480, 0, 0, 0, 0);
92 ret = SetEvent(p->window_created);
93 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
95 for (;;)
97 MSG msg;
99 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
100 DispatchMessageA(&msg);
101 res = WaitForSingleObject(p->destroy_window, 100);
102 if (res == WAIT_OBJECT_0)
103 break;
104 if (res != WAIT_TIMEOUT)
106 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
107 break;
111 DestroyWindow(p->window);
113 return 0;
116 static void create_window_thread(struct create_window_thread_param *p)
118 DWORD res, tid;
120 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
121 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
122 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
123 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
124 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
125 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
126 res = WaitForSingleObject(p->window_created, INFINITE);
127 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
130 static void destroy_window_thread(struct create_window_thread_param *p)
132 SetEvent(p->destroy_window);
133 WaitForSingleObject(p->thread, INFINITE);
134 CloseHandle(p->destroy_window);
135 CloseHandle(p->window_created);
136 CloseHandle(p->thread);
139 static IDirectDrawSurface4 *get_depth_stencil(IDirect3DDevice3 *device)
141 IDirectDrawSurface4 *rt, *ret;
142 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, 0};
143 HRESULT hr;
145 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
146 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
147 hr = IDirectDrawSurface4_GetAttachedSurface(rt, &caps, &ret);
148 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
149 IDirectDrawSurface4_Release(rt);
150 return ret;
153 static D3DCOLOR get_surface_color(IDirectDrawSurface4 *surface, UINT x, UINT y)
155 RECT rect = {x, y, x + 1, y + 1};
156 DDSURFACEDESC2 surface_desc;
157 D3DCOLOR color;
158 HRESULT hr;
160 memset(&surface_desc, 0, sizeof(surface_desc));
161 surface_desc.dwSize = sizeof(surface_desc);
163 hr = IDirectDrawSurface4_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
164 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
165 if (FAILED(hr))
166 return 0xdeadbeef;
168 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
170 hr = IDirectDrawSurface4_Unlock(surface, &rect);
171 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
173 return color;
176 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
178 DDPIXELFORMAT *z_fmt = ctx;
180 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
181 *z_fmt = *format;
183 return DDENUMRET_OK;
186 static IDirectDraw4 *create_ddraw(void)
188 IDirectDraw4 *ddraw4;
189 IDirectDraw *ddraw1;
190 HRESULT hr;
192 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
193 return NULL;
195 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4);
196 IDirectDraw_Release(ddraw1);
197 if (FAILED(hr))
198 return NULL;
200 return ddraw4;
203 static IDirect3DDevice3 *create_device(HWND window, DWORD coop_level)
205 IDirectDrawSurface4 *surface, *ds;
206 IDirect3DDevice3 *device = NULL;
207 DDSURFACEDESC2 surface_desc;
208 IDirectDraw4 *ddraw4;
209 DDPIXELFORMAT z_fmt;
210 IDirect3D3 *d3d3;
211 HRESULT hr;
213 if (!(ddraw4 = create_ddraw()))
214 return NULL;
216 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, coop_level);
217 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
219 memset(&surface_desc, 0, sizeof(surface_desc));
220 surface_desc.dwSize = sizeof(surface_desc);
221 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
222 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
223 surface_desc.dwWidth = 640;
224 surface_desc.dwHeight = 480;
226 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &surface, NULL);
227 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
229 if (coop_level & DDSCL_NORMAL)
231 IDirectDrawClipper *clipper;
233 hr = IDirectDraw4_CreateClipper(ddraw4, 0, &clipper, NULL);
234 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
235 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
236 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
237 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
238 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
239 IDirectDrawClipper_Release(clipper);
242 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirect3D3, (void **)&d3d3);
243 IDirectDraw4_Release(ddraw4);
244 if (FAILED(hr))
246 IDirectDrawSurface4_Release(surface);
247 return NULL;
250 memset(&z_fmt, 0, sizeof(z_fmt));
251 hr = IDirect3D3_EnumZBufferFormats(d3d3, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
252 if (FAILED(hr) || !z_fmt.dwSize)
254 IDirect3D3_Release(d3d3);
255 IDirectDrawSurface4_Release(surface);
256 return NULL;
259 memset(&surface_desc, 0, sizeof(surface_desc));
260 surface_desc.dwSize = sizeof(surface_desc);
261 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
262 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
263 U4(surface_desc).ddpfPixelFormat = z_fmt;
264 surface_desc.dwWidth = 640;
265 surface_desc.dwHeight = 480;
266 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &ds, NULL);
267 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
268 if (FAILED(hr))
270 IDirect3D3_Release(d3d3);
271 IDirectDrawSurface4_Release(surface);
272 return NULL;
275 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
276 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
277 IDirectDrawSurface4_Release(ds);
278 if (FAILED(hr))
280 IDirect3D3_Release(d3d3);
281 IDirectDrawSurface4_Release(surface);
282 return NULL;
285 hr = IDirect3D3_CreateDevice(d3d3, &IID_IDirect3DHALDevice, surface, &device, NULL);
286 IDirect3D3_Release(d3d3);
287 IDirectDrawSurface4_Release(surface);
288 if (FAILED(hr))
289 return NULL;
291 return device;
294 static IDirect3DViewport3 *create_viewport(IDirect3DDevice3 *device, UINT x, UINT y, UINT w, UINT h)
296 IDirect3DViewport3 *viewport;
297 D3DVIEWPORT2 vp;
298 IDirect3D3 *d3d;
299 HRESULT hr;
301 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
302 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
303 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
304 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
305 hr = IDirect3DDevice3_AddViewport(device, viewport);
306 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
307 memset(&vp, 0, sizeof(vp));
308 vp.dwSize = sizeof(vp);
309 vp.dwX = x;
310 vp.dwY = y;
311 vp.dwWidth = w;
312 vp.dwHeight = h;
313 vp.dvClipX = -1.0f;
314 vp.dvClipY = 1.0f;
315 vp.dvClipWidth = 2.0f;
316 vp.dvClipHeight = 2.0f;
317 vp.dvMinZ = 0.0f;
318 vp.dvMaxZ = 1.0f;
319 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
320 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
321 IDirect3D3_Release(d3d);
323 return viewport;
326 static void destroy_viewport(IDirect3DDevice3 *device, IDirect3DViewport3 *viewport)
328 HRESULT hr;
330 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
331 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
332 IDirect3DViewport3_Release(viewport);
335 static const UINT *expect_messages;
337 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
339 if (expect_messages && message == *expect_messages)
340 ++expect_messages;
342 return DefWindowProcA(hwnd, message, wparam, lparam);
345 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
346 * interface. This prevents subsequent SetCooperativeLevel() calls on a
347 * different window from failing with DDERR_HWNDALREADYSET. */
348 static void fix_wndproc(HWND window, LONG_PTR proc)
350 IDirectDraw4 *ddraw;
351 HRESULT hr;
353 if (!(ddraw = create_ddraw()))
354 return;
356 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
357 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
358 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
359 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
360 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
362 IDirectDraw4_Release(ddraw);
365 static void test_process_vertices(void)
367 IDirect3DVertexBuffer *src_vb, *dst_vb;
368 IDirect3DViewport3 *viewport;
369 D3DVERTEXBUFFERDESC vb_desc;
370 IDirect3DDevice3 *device;
371 struct vec3 *src_data;
372 struct vec4 *dst_data;
373 IDirect3D3 *d3d3;
374 D3DVIEWPORT2 vp2;
375 D3DVIEWPORT vp1;
376 HWND window;
377 HRESULT hr;
379 static D3DMATRIX identity =
381 1.0f, 0.0f, 0.0f, 0.0f,
382 0.0f, 1.0f, 0.0f, 0.0f,
383 0.0f, 0.0f, 1.0f, 0.0f,
384 0.0f, 0.0f, 0.0f, 1.0f,
386 static D3DMATRIX projection =
388 1.0f, 0.0f, 0.0f, 0.0f,
389 0.0f, 1.0f, 0.0f, 0.0f,
390 0.0f, 0.0f, 1.0f, 0.0f,
391 6.0f, 7.0f, 8.0f, 1.0f,
394 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
395 0, 0, 640, 480, 0, 0, 0, 0);
396 if (!(device = create_device(window, DDSCL_NORMAL)))
398 skip("Failed to create a 3D device, skipping test.\n");
399 DestroyWindow(window);
400 return;
403 hr = IDirect3DDevice3_GetDirect3D(device, &d3d3);
404 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
406 memset(&vb_desc, 0, sizeof(vb_desc));
407 vb_desc.dwSize = sizeof(vb_desc);
408 vb_desc.dwFVF = D3DFVF_XYZ;
409 vb_desc.dwNumVertices = 3;
410 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &src_vb, 0, NULL);
411 ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
413 hr = IDirect3DVertexBuffer_Lock(src_vb, DDLOCK_WRITEONLY, (void **)&src_data, NULL);
414 ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
415 src_data[0].x = -1.0f;
416 src_data[0].y = -1.0f;
417 src_data[0].z = -1.0f;
418 src_data[1].x = 0.0f;
419 src_data[1].y = 0.0f;
420 src_data[1].z = 0.0f;
421 src_data[2].x = 1.0f;
422 src_data[2].y = 1.0f;
423 src_data[2].z = 1.0f;
424 hr = IDirect3DVertexBuffer_Unlock(src_vb);
425 ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#x.\n", hr);
427 memset(&vb_desc, 0, sizeof(vb_desc));
428 vb_desc.dwSize = sizeof(vb_desc);
429 vb_desc.dwFVF = D3DFVF_XYZRHW;
430 vb_desc.dwNumVertices = 3;
431 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &dst_vb, 0, NULL);
432 ok(SUCCEEDED(hr), "Failed to create destination vertex buffer, hr %#x.\n", hr);
434 hr = IDirect3D3_CreateViewport(d3d3, &viewport, NULL);
435 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
436 hr = IDirect3DDevice3_AddViewport(device, viewport);
437 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
438 vp2.dwSize = sizeof(vp2);
439 vp2.dwX = 10;
440 vp2.dwY = 20;
441 vp2.dwWidth = 100;
442 vp2.dwHeight = 200;
443 vp2.dvClipX = 2.0f;
444 vp2.dvClipY = 3.0f;
445 vp2.dvClipWidth = 4.0f;
446 vp2.dvClipHeight = 5.0f;
447 vp2.dvMinZ = -2.0f;
448 vp2.dvMaxZ = 3.0f;
449 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
450 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
451 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
452 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
454 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
455 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
456 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &identity);
457 ok(SUCCEEDED(hr), "Failed to set view transformation, hr %#x.\n", hr);
458 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
459 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
461 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
462 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
464 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
465 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
466 ok(compare_vec4(&dst_data[0], -6.500e+1f, +1.800e+2f, +2.000e-1f, +1.000e+0f, 4096),
467 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
468 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
469 ok(compare_vec4(&dst_data[1], -4.000e+1f, +1.400e+2f, +4.000e-1f, +1.000e+0f, 4096),
470 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
471 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
472 ok(compare_vec4(&dst_data[2], -1.500e+1f, +1.000e+2f, +6.000e-1f, +1.000e+0f, 4096),
473 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
474 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
475 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
476 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
478 hr = IDirect3DDevice3_MultiplyTransform(device, D3DTRANSFORMSTATE_PROJECTION, &projection);
479 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
481 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
482 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
484 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
485 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
486 ok(compare_vec4(&dst_data[0], +8.500e+1f, -1.000e+2f, +1.800e+0f, +1.000e+0f, 4096),
487 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
488 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
489 ok(compare_vec4(&dst_data[1], +1.100e+2f, -1.400e+2f, +2.000e+0f, +1.000e+0f, 4096),
490 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
491 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
492 ok(compare_vec4(&dst_data[2], +1.350e+2f, -1.800e+2f, +2.200e+0f, +1.000e+0f, 4096),
493 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
494 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
495 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
496 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
498 vp2.dwSize = sizeof(vp2);
499 vp2.dwX = 30;
500 vp2.dwY = 40;
501 vp2.dwWidth = 90;
502 vp2.dwHeight = 80;
503 vp2.dvClipX = 4.0f;
504 vp2.dvClipY = 6.0f;
505 vp2.dvClipWidth = 2.0f;
506 vp2.dvClipHeight = 4.0f;
507 vp2.dvMinZ = 3.0f;
508 vp2.dvMaxZ = -2.0f;
509 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
510 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
512 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
513 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
515 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
516 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
517 ok(compare_vec4(&dst_data[0], +7.500e+1f, +4.000e+1f, -8.000e-1f, +1.000e+0f, 4096),
518 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
519 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
520 ok(compare_vec4(&dst_data[1], +1.200e+2f, +2.000e+1f, -1.000e+0f, +1.000e+0f, 4096),
521 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
522 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
523 ok(compare_vec4(&dst_data[2], +1.650e+2f, +0.000e+0f, -1.200e+0f, +1.000e+0f, 4096),
524 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
525 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
526 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
527 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
529 vp1.dwSize = sizeof(vp1);
530 vp1.dwX = 30;
531 vp1.dwY = 40;
532 vp1.dwWidth = 90;
533 vp1.dwHeight = 80;
534 vp1.dvScaleX = 7.0f;
535 vp1.dvScaleY = 2.0f;
536 vp1.dvMaxX = 6.0f;
537 vp1.dvMaxY = 10.0f;
538 vp1.dvMinZ = -2.0f;
539 vp1.dvMaxZ = 3.0f;
540 hr = IDirect3DViewport3_SetViewport(viewport, &vp1);
541 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
543 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
544 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
546 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
547 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
548 ok(compare_vec4(&dst_data[0], +1.100e+2f, +6.800e+1f, +7.000e+0f, +1.000e+0f, 4096),
549 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
550 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
551 ok(compare_vec4(&dst_data[1], +1.170e+2f, +6.600e+1f, +8.000e+0f, +1.000e+0f, 4096),
552 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
553 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
554 ok(compare_vec4(&dst_data[2], +1.240e+2f, +6.400e+1f, +9.000e+0f, +1.000e+0f, 4096),
555 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
556 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
557 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
558 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
560 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
561 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
563 IDirect3DVertexBuffer_Release(dst_vb);
564 IDirect3DVertexBuffer_Release(src_vb);
565 IDirect3DViewport3_Release(viewport);
566 IDirect3D3_Release(d3d3);
567 IDirect3DDevice3_Release(device);
568 DestroyWindow(window);
571 static void test_coop_level_create_device_window(void)
573 HWND focus_window, device_window;
574 IDirectDraw4 *ddraw;
575 HRESULT hr;
577 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
578 0, 0, 640, 480, 0, 0, 0, 0);
579 if (!(ddraw = create_ddraw()))
581 skip("Failed to create a ddraw object, skipping test.\n");
582 DestroyWindow(focus_window);
583 return;
586 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
587 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
588 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
589 ok(!device_window, "Unexpected device window found.\n");
590 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
591 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
592 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
593 ok(!device_window, "Unexpected device window found.\n");
594 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
595 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
596 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
597 ok(!device_window, "Unexpected device window found.\n");
598 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
599 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
600 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
601 ok(!device_window, "Unexpected device window found.\n");
602 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
603 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
604 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
605 ok(!device_window, "Unexpected device window found.\n");
607 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
608 if (broken(hr == DDERR_INVALIDPARAMS))
610 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
611 IDirectDraw4_Release(ddraw);
612 DestroyWindow(focus_window);
613 return;
616 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
617 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
618 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
619 ok(!device_window, "Unexpected device window found.\n");
620 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
621 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
622 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
623 ok(!device_window, "Unexpected device window found.\n");
625 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
626 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
627 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
628 ok(!device_window, "Unexpected device window found.\n");
629 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
630 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
631 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
632 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
633 ok(!!device_window, "Device window not found.\n");
635 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
636 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
637 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
638 ok(!device_window, "Unexpected device window found.\n");
639 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
640 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
641 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
642 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
643 ok(!!device_window, "Device window not found.\n");
645 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
646 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
647 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
648 ok(!device_window, "Unexpected device window found.\n");
649 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
650 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
651 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
652 ok(!device_window, "Unexpected device window found.\n");
653 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
654 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
655 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
656 ok(!device_window, "Unexpected device window found.\n");
657 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
658 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
659 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
660 ok(!!device_window, "Device window not found.\n");
662 IDirectDraw4_Release(ddraw);
663 DestroyWindow(focus_window);
666 static void test_clipper_blt(void)
668 IDirectDrawSurface4 *src_surface, *dst_surface;
669 RECT client_rect, src_rect;
670 IDirectDrawClipper *clipper;
671 DDSURFACEDESC2 surface_desc;
672 unsigned int i, j, x, y;
673 IDirectDraw4 *ddraw;
674 RGNDATA *rgn_data;
675 D3DCOLOR color;
676 HRGN r1, r2;
677 HWND window;
678 DDBLTFX fx;
679 HRESULT hr;
680 DWORD *ptr;
681 DWORD ret;
683 static const DWORD src_data[] =
685 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
686 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
687 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
689 static const D3DCOLOR expected1[] =
691 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
692 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
693 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
694 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
696 static const D3DCOLOR expected2[] =
698 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
699 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
700 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
701 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
704 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
705 10, 10, 640, 480, 0, 0, 0, 0);
706 ShowWindow(window, SW_SHOW);
707 if (!(ddraw = create_ddraw()))
709 skip("Failed to create a ddraw object, skipping test.\n");
710 DestroyWindow(window);
711 return;
714 ret = GetClientRect(window, &client_rect);
715 ok(ret, "Failed to get client rect.\n");
716 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
717 ok(ret, "Failed to map client rect.\n");
719 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
720 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
722 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
723 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
724 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
725 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
726 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
727 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
728 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
729 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
730 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
731 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
732 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
733 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
734 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
735 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
736 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
737 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
738 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
739 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
740 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
741 HeapFree(GetProcessHeap(), 0, rgn_data);
743 r1 = CreateRectRgn(0, 0, 320, 240);
744 ok(!!r1, "Failed to create region.\n");
745 r2 = CreateRectRgn(320, 240, 640, 480);
746 ok(!!r2, "Failed to create region.\n");
747 CombineRgn(r1, r1, r2, RGN_OR);
748 ret = GetRegionData(r1, 0, NULL);
749 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
750 ret = GetRegionData(r1, ret, rgn_data);
751 ok(!!ret, "Failed to get region data.\n");
753 DeleteObject(r2);
754 DeleteObject(r1);
756 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
757 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
758 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
759 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
760 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
761 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
763 HeapFree(GetProcessHeap(), 0, rgn_data);
765 memset(&surface_desc, 0, sizeof(surface_desc));
766 surface_desc.dwSize = sizeof(surface_desc);
767 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
768 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
769 surface_desc.dwWidth = 640;
770 surface_desc.dwHeight = 480;
771 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
772 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
773 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
774 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
775 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
776 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
778 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
779 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
780 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
781 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
783 memset(&fx, 0, sizeof(fx));
784 fx.dwSize = sizeof(fx);
785 hr = IDirectDrawSurface4_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
786 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
787 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
788 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
790 hr = IDirectDrawSurface4_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
791 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
792 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
793 ptr = surface_desc.lpSurface;
794 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
795 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
796 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
797 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
798 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
800 hr = IDirectDrawSurface4_SetClipper(dst_surface, clipper);
801 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
803 SetRect(&src_rect, 1, 1, 5, 2);
804 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
805 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
806 for (i = 0; i < 4; ++i)
808 for (j = 0; j < 4; ++j)
810 x = 80 * ((2 * j) + 1);
811 y = 60 * ((2 * i) + 1);
812 color = get_surface_color(dst_surface, x, y);
813 ok(compare_color(color, expected1[i * 4 + j], 1),
814 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
818 U5(fx).dwFillColor = 0xff0000ff;
819 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
820 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
821 for (i = 0; i < 4; ++i)
823 for (j = 0; j < 4; ++j)
825 x = 80 * ((2 * j) + 1);
826 y = 60 * ((2 * i) + 1);
827 color = get_surface_color(dst_surface, x, y);
828 ok(compare_color(color, expected2[i * 4 + j], 1),
829 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
833 hr = IDirectDrawSurface4_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
834 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
836 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
837 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
838 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
839 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
840 DestroyWindow(window);
841 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
842 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
843 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
844 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
845 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
846 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
847 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
848 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
849 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
850 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
851 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
852 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
854 IDirectDrawSurface4_Release(dst_surface);
855 IDirectDrawSurface4_Release(src_surface);
856 IDirectDrawClipper_Release(clipper);
857 IDirectDraw4_Release(ddraw);
860 static void test_coop_level_d3d_state(void)
862 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
863 IDirectDrawSurface4 *rt, *surface;
864 IDirect3DViewport3 *viewport;
865 IDirect3DDevice3 *device;
866 IDirectDraw4 *ddraw;
867 IDirect3D3 *d3d;
868 D3DCOLOR color;
869 DWORD value;
870 HWND window;
871 HRESULT hr;
873 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
874 0, 0, 640, 480, 0, 0, 0, 0);
875 if (!(device = create_device(window, DDSCL_NORMAL)))
877 skip("Failed to create a 3D device, skipping test.\n");
878 DestroyWindow(window);
879 return;
882 viewport = create_viewport(device, 0, 0, 640, 480);
884 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
885 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
886 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
887 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
888 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
889 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
890 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
891 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
892 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
893 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
894 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
895 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
896 color = get_surface_color(rt, 320, 240);
897 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
899 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
900 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
901 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
902 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
903 IDirect3D3_Release(d3d);
904 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
905 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
906 hr = IDirectDrawSurface4_IsLost(rt);
907 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
908 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
909 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
910 IDirectDraw4_Release(ddraw);
912 hr = IDirect3DDevice3_GetRenderTarget(device, &surface);
913 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
914 ok(surface == rt, "Got unexpected surface %p.\n", surface);
915 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
916 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
917 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
918 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
919 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
920 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
921 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
922 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
923 color = get_surface_color(rt, 320, 240);
924 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
926 destroy_viewport(device, viewport);
927 IDirectDrawSurface4_Release(surface);
928 IDirectDrawSurface4_Release(rt);
929 IDirect3DDevice3_Release(device);
930 DestroyWindow(window);
933 static void test_surface_interface_mismatch(void)
935 IDirectDraw4 *ddraw = NULL;
936 IDirect3D3 *d3d = NULL;
937 IDirectDrawSurface4 *surface = NULL, *ds;
938 IDirectDrawSurface3 *surface3 = NULL;
939 IDirect3DDevice3 *device = NULL;
940 IDirect3DViewport3 *viewport = NULL;
941 DDSURFACEDESC2 surface_desc;
942 DDPIXELFORMAT z_fmt;
943 ULONG refcount;
944 HRESULT hr;
945 D3DCOLOR color;
946 HWND window;
947 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
949 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
950 0, 0, 640, 480, 0, 0, 0, 0);
952 if (!(ddraw = create_ddraw()))
954 skip("Failed to create a ddraw object, skipping test.\n");
955 goto cleanup;
958 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
959 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
961 memset(&surface_desc, 0, sizeof(surface_desc));
962 surface_desc.dwSize = sizeof(surface_desc);
963 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
964 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
965 surface_desc.dwWidth = 640;
966 surface_desc.dwHeight = 480;
968 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
969 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
971 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
972 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
974 if (FAILED(hr = IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
976 skip("D3D interface is not available, skipping test.\n");
977 goto cleanup;
980 memset(&z_fmt, 0, sizeof(z_fmt));
981 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
982 if (FAILED(hr) || !z_fmt.dwSize)
984 skip("No depth buffer formats available, skipping test.\n");
985 goto cleanup;
988 memset(&surface_desc, 0, sizeof(surface_desc));
989 surface_desc.dwSize = sizeof(surface_desc);
990 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
991 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
992 U4(surface_desc).ddpfPixelFormat = z_fmt;
993 surface_desc.dwWidth = 640;
994 surface_desc.dwHeight = 480;
995 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
996 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
997 if (FAILED(hr))
998 goto cleanup;
1000 /* Using a different surface interface version still works */
1001 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1002 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1003 refcount = IDirectDrawSurface4_Release(ds);
1004 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1005 if (FAILED(hr))
1006 goto cleanup;
1008 /* Here too */
1009 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface4 *)surface3, &device, NULL);
1010 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1011 if (FAILED(hr))
1012 goto cleanup;
1014 viewport = create_viewport(device, 0, 0, 640, 480);
1016 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1017 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1018 color = get_surface_color(surface, 320, 240);
1019 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1021 cleanup:
1022 if (viewport)
1023 destroy_viewport(device, viewport);
1024 if (surface3) IDirectDrawSurface3_Release(surface3);
1025 if (surface) IDirectDrawSurface4_Release(surface);
1026 if (device) IDirect3DDevice3_Release(device);
1027 if (d3d) IDirect3D3_Release(d3d);
1028 if (ddraw) IDirectDraw4_Release(ddraw);
1029 DestroyWindow(window);
1032 static void test_coop_level_threaded(void)
1034 struct create_window_thread_param p;
1035 IDirectDraw4 *ddraw;
1036 HRESULT hr;
1038 if (!(ddraw = create_ddraw()))
1040 skip("Failed to create a ddraw object, skipping test.\n");
1041 return;
1043 create_window_thread(&p);
1045 hr = IDirectDraw4_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1046 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1048 IDirectDraw4_Release(ddraw);
1049 destroy_window_thread(&p);
1052 static void test_depth_blit(void)
1054 static struct
1056 float x, y, z;
1057 DWORD color;
1059 quad1[] =
1061 { -1.0, 1.0, 0.50f, 0xff00ff00},
1062 { 1.0, 1.0, 0.50f, 0xff00ff00},
1063 { -1.0, -1.0, 0.50f, 0xff00ff00},
1064 { 1.0, -1.0, 0.50f, 0xff00ff00},
1066 static const D3DCOLOR expected_colors[4][4] =
1068 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1069 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1070 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1071 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1073 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1075 IDirect3DDevice3 *device;
1076 IDirectDrawSurface4 *ds1, *ds2, *ds3, *rt;
1077 IDirect3DViewport3 *viewport;
1078 RECT src_rect, dst_rect;
1079 unsigned int i, j;
1080 D3DCOLOR color;
1081 HRESULT hr;
1082 IDirect3D3 *d3d;
1083 IDirectDraw4 *ddraw;
1084 DDBLTFX fx;
1085 HWND window;
1086 D3DRECT d3drect;
1088 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1089 0, 0, 640, 480, 0, 0, 0, 0);
1090 if (!(device = create_device(window, DDSCL_NORMAL)))
1092 skip("Failed to create a 3D device, skipping test.\n");
1093 DestroyWindow(window);
1094 return;
1097 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1098 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
1099 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1100 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
1101 IDirect3D3_Release(d3d);
1103 ds1 = get_depth_stencil(device);
1105 memset(&ddsd_new, 0, sizeof(ddsd_new));
1106 ddsd_new.dwSize = sizeof(ddsd_new);
1107 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1108 ddsd_existing.dwSize = sizeof(ddsd_existing);
1109 hr = IDirectDrawSurface4_GetSurfaceDesc(ds1, &ddsd_existing);
1110 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1111 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1112 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1113 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1114 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1115 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1116 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1117 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1118 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1119 IDirectDraw4_Release(ddraw);
1121 viewport = create_viewport(device, 0, 0, ddsd_existing.dwWidth, ddsd_existing.dwHeight);
1122 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1123 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
1125 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1126 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1127 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1128 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1130 U1(d3drect).x1 = U2(d3drect).y1 = 0;
1131 U3(d3drect).x2 = ddsd_existing.dwWidth; U4(d3drect).y2 = ddsd_existing.dwHeight;
1132 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1133 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1135 /* Partial blit. */
1136 SetRect(&src_rect, 0, 0, 320, 240);
1137 SetRect(&dst_rect, 0, 0, 320, 240);
1138 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1139 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1140 /* Different locations. */
1141 SetRect(&src_rect, 0, 0, 320, 240);
1142 SetRect(&dst_rect, 320, 240, 640, 480);
1143 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1144 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1145 /* Streched. */
1146 SetRect(&src_rect, 0, 0, 320, 240);
1147 SetRect(&dst_rect, 0, 0, 640, 480);
1148 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1149 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1150 /* Flipped. */
1151 SetRect(&src_rect, 0, 480, 640, 0);
1152 SetRect(&dst_rect, 0, 0, 640, 480);
1153 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1154 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1155 SetRect(&src_rect, 0, 0, 640, 480);
1156 SetRect(&dst_rect, 0, 480, 640, 0);
1157 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1158 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1159 /* Full, explicit. */
1160 SetRect(&src_rect, 0, 0, 640, 480);
1161 SetRect(&dst_rect, 0, 0, 640, 480);
1162 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1163 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1164 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1166 /* Depth blit inside a BeginScene / EndScene pair */
1167 hr = IDirect3DDevice3_BeginScene(device);
1168 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1169 /* From the current depth stencil */
1170 hr = IDirectDrawSurface4_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1171 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1172 /* To the current depth stencil */
1173 hr = IDirectDrawSurface4_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1174 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1175 /* Between unbound surfaces */
1176 hr = IDirectDrawSurface4_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1177 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1178 hr = IDirect3DDevice3_EndScene(device);
1179 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1181 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1182 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1183 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1184 * a reliable result(z = 0.0) */
1185 memset(&fx, 0, sizeof(fx));
1186 fx.dwSize = sizeof(fx);
1187 hr = IDirectDrawSurface4_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1188 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1190 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1191 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1192 SetRect(&dst_rect, 0, 0, 320, 240);
1193 hr = IDirectDrawSurface4_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1194 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1195 IDirectDrawSurface4_Release(ds3);
1196 IDirectDrawSurface4_Release(ds2);
1197 IDirectDrawSurface4_Release(ds1);
1199 hr = IDirect3DDevice3_BeginScene(device);
1200 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1201 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1202 quad1, 4, 0);
1203 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1204 hr = IDirect3DDevice3_EndScene(device);
1205 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1207 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1208 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1209 for (i = 0; i < 4; ++i)
1211 for (j = 0; j < 4; ++j)
1213 unsigned int x = 80 * ((2 * j) + 1);
1214 unsigned int y = 60 * ((2 * i) + 1);
1215 color = get_surface_color(rt, x, y);
1216 ok(compare_color(color, expected_colors[i][j], 1),
1217 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1220 IDirectDrawSurface4_Release(rt);
1222 destroy_viewport(device, viewport);
1223 IDirect3DDevice3_Release(device);
1224 DestroyWindow(window);
1227 static void test_texture_load_ckey(void)
1229 IDirectDraw4 *ddraw;
1230 IDirectDrawSurface4 *src;
1231 IDirectDrawSurface4 *dst;
1232 IDirect3DTexture2 *src_tex;
1233 IDirect3DTexture2 *dst_tex;
1234 DDSURFACEDESC2 ddsd;
1235 HRESULT hr;
1236 DDCOLORKEY ckey;
1238 if (!(ddraw = create_ddraw()))
1240 skip("Failed to create a ddraw object, skipping test.\n");
1241 return;
1243 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1244 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1246 memset(&ddsd, 0, sizeof(ddsd));
1247 ddsd.dwSize = sizeof(ddsd);
1248 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1249 ddsd.dwHeight = 128;
1250 ddsd.dwWidth = 128;
1251 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1252 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &src, NULL);
1253 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1254 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1255 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &dst, NULL);
1256 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1258 hr = IDirectDrawSurface4_QueryInterface(src, &IID_IDirect3DTexture2, (void **)&src_tex);
1259 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture2 interface, hr %#x.\n", hr);
1260 if (FAILED(hr))
1262 /* 64 bit ddraw does not support d3d */
1263 skip("Could not get Direct3DTexture2 interface, skipping texture::Load color keying tests.\n");
1264 IDirectDrawSurface4_Release(dst);
1265 IDirectDrawSurface4_Release(src);
1266 IDirectDraw4_Release(ddraw);
1267 return;
1269 hr = IDirectDrawSurface4_QueryInterface(dst, &IID_IDirect3DTexture2, (void **)&dst_tex);
1270 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture2 interface, hr %#x.\n", hr);
1272 /* No surface has a color key */
1273 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1274 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1275 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1276 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1277 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1278 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1279 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1281 /* Source surface has a color key */
1282 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1283 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1284 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1285 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1286 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1287 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1288 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1289 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1290 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1292 /* Both surfaces have a color key: Dest ckey is overwritten */
1293 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1294 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1295 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1296 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1297 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1298 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1299 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1300 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1301 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1303 /* Only the destination has a color key: It is not deleted */
1304 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1305 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1306 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1307 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1308 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1309 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1310 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1311 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1312 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1313 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1315 IDirect3DTexture2_Release(dst_tex);
1316 IDirect3DTexture2_Release(src_tex);
1317 IDirectDrawSurface4_Release(dst);
1318 IDirectDrawSurface4_Release(src);
1319 IDirectDraw4_Release(ddraw);
1322 static ULONG get_refcount(IUnknown *test_iface)
1324 IUnknown_AddRef(test_iface);
1325 return IUnknown_Release(test_iface);
1328 static void test_viewport(void)
1330 IDirectDraw4 *ddraw;
1331 IDirect3D3 *d3d;
1332 HRESULT hr, old_d3d_ref;
1333 ULONG ref;
1334 IDirect3DViewport *viewport;
1335 IDirect3DViewport2 *viewport2;
1336 IDirect3DViewport3 *viewport3, *another_vp, *test_vp;
1337 IDirectDrawGammaControl *gamma;
1338 IUnknown *unknown;
1339 HWND window;
1340 IDirect3DDevice3 *device;
1342 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1343 0, 0, 640, 480, 0, 0, 0, 0);
1344 if (!(device = create_device(window, DDSCL_NORMAL)))
1346 skip("Failed to create a 3D device, skipping test.\n");
1347 DestroyWindow(window);
1348 return;
1350 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1351 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
1352 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1353 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
1354 old_d3d_ref = get_refcount((IUnknown *) d3d);
1356 hr = IDirect3D3_CreateViewport(d3d, &viewport3, NULL);
1357 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1358 ref = get_refcount((IUnknown *)viewport3);
1359 ok(ref == 1, "Initial IDirect3DViewport3 refcount is %u\n", ref);
1360 ref = get_refcount((IUnknown *)d3d);
1361 ok(ref == old_d3d_ref, "IDirect3D3 refcount is %u\n", ref);
1363 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1364 hr = IDirect3DViewport2_QueryInterface(viewport3, &IID_IDirectDrawGammaControl, (void **)&gamma);
1365 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1366 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1367 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1368 /* NULL iid: Segfaults */
1370 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport, (void **)&viewport);
1371 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1372 if (viewport)
1374 ref = get_refcount((IUnknown *)viewport);
1375 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1376 ref = get_refcount((IUnknown *)viewport3);
1377 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1378 IDirect3DViewport_Release(viewport);
1379 viewport = NULL;
1382 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport3, (void **)&viewport2);
1383 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1384 if (viewport2)
1386 ref = get_refcount((IUnknown *)viewport2);
1387 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1388 ref = get_refcount((IUnknown *)viewport3);
1389 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1390 IDirect3DViewport3_Release(viewport2);
1393 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IUnknown, (void **)&unknown);
1394 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1395 if (unknown)
1397 ref = get_refcount((IUnknown *)viewport3);
1398 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1399 ref = get_refcount(unknown);
1400 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1401 IUnknown_Release(unknown);
1404 /* AddViewport(NULL): Segfault */
1405 hr = IDirect3DDevice3_DeleteViewport(device, NULL);
1406 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1407 hr = IDirect3DDevice3_GetCurrentViewport(device, NULL);
1408 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1410 hr = IDirect3D3_CreateViewport(d3d, &another_vp, NULL);
1411 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1413 /* Setting a viewport not in the viewport list fails */
1414 hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
1415 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1417 hr = IDirect3DDevice3_AddViewport(device, viewport3);
1418 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1419 ref = get_refcount((IUnknown *) viewport3);
1420 ok(ref == 2, "viewport3 refcount is %d\n", ref);
1421 hr = IDirect3DDevice3_AddViewport(device, another_vp);
1422 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1423 ref = get_refcount((IUnknown *) another_vp);
1424 ok(ref == 2, "another_vp refcount is %d\n", ref);
1426 test_vp = (IDirect3DViewport3 *) 0xbaadc0de;
1427 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1428 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1429 ok(test_vp == (IDirect3DViewport3 *) 0xbaadc0de, "Got unexpected pointer %p\n", test_vp);
1431 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
1432 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1433 ref = get_refcount((IUnknown *) viewport3);
1434 ok(ref == 3, "viewport3 refcount is %d\n", ref);
1435 ref = get_refcount((IUnknown *) device);
1436 ok(ref == 1, "device refcount is %d\n", ref);
1438 test_vp = NULL;
1439 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1440 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1441 ok(test_vp == viewport3, "Got unexpected viewport %p\n", test_vp);
1442 ref = get_refcount((IUnknown *) viewport3);
1443 ok(ref == 4, "viewport3 refcount is %d\n", ref);
1444 if(test_vp) IDirect3DViewport3_Release(test_vp);
1446 /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
1448 /* Cannot set the viewport to NULL */
1449 hr = IDirect3DDevice3_SetCurrentViewport(device, NULL);
1450 ok(hr == DDERR_INVALIDPARAMS, "Failed to set viewport to NULL, hr %#x.\n", hr);
1451 test_vp = NULL;
1452 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1453 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1454 ok(test_vp == viewport3, "Got unexpected viewport %p\n", test_vp);
1455 if(test_vp) IDirect3DViewport3_Release(test_vp);
1457 /* SetCurrentViewport properly releases the old viewport's reference */
1458 hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
1459 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1460 ref = get_refcount((IUnknown *) viewport3);
1461 ok(ref == 2, "viewport3 refcount is %d\n", ref);
1462 ref = get_refcount((IUnknown *) another_vp);
1463 ok(ref == 3, "another_vp refcount is %d\n", ref);
1465 /* Unlike device2::DeleteViewport, device3::DeleteViewport releases the
1466 * reference held by SetCurrentViewport */
1467 hr = IDirect3DDevice3_DeleteViewport(device, another_vp);
1468 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1469 ref = get_refcount((IUnknown *) another_vp);
1470 ok(ref == 1, "another_vp refcount is %d\n", ref);
1472 /* GetCurrentViewport still fails */
1473 test_vp = NULL;
1474 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1475 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1476 ok(test_vp == NULL, "Got unexpected viewport %p\n", test_vp);
1477 if(test_vp) IDirect3DViewport3_Release(test_vp);
1479 /* Setting a different viewport doesn't have any surprises now */
1480 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
1481 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1482 ref = get_refcount((IUnknown *) viewport3);
1483 ok(ref == 3, "viewport3 refcount is %d\n", ref);
1484 ref = get_refcount((IUnknown *) another_vp);
1485 ok(ref == 1, "another_vp refcount is %d\n", ref);
1487 /* Destroying the device removes the viewport and releases the reference */
1488 IDirect3DDevice3_Release(device);
1489 ref = get_refcount((IUnknown *) viewport3);
1490 ok(ref == 1, "viewport3 refcount is %d\n", ref);
1492 ref = IDirect3DViewport3_Release(another_vp);
1493 ok(ref == 0, "Got unexpected ref %d\n", ref);
1494 ref = IDirect3DViewport3_Release(viewport3);
1495 ok(ref == 0, "Got unexpected ref %d\n", ref);
1496 IDirect3D3_Release(d3d);
1497 DestroyWindow(window);
1498 IDirectDraw4_Release(ddraw);
1501 static void test_zenable(void)
1503 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1504 static struct
1506 struct vec4 position;
1507 D3DCOLOR diffuse;
1509 tquad[] =
1511 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
1512 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xff00ff00},
1513 {{640.0f, 480.0f, 1.5f, 1.0f}, 0xff00ff00},
1514 {{640.0f, 0.0f, 1.5f, 1.0f}, 0xff00ff00},
1516 IDirect3DViewport3 *viewport;
1517 IDirect3DDevice3 *device;
1518 IDirectDrawSurface4 *rt;
1519 D3DCOLOR color;
1520 HWND window;
1521 HRESULT hr;
1522 UINT x, y;
1523 UINT i, j;
1525 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1526 0, 0, 640, 480, 0, 0, 0, 0);
1527 if (!(device = create_device(window, DDSCL_NORMAL)))
1529 skip("Failed to create a 3D device, skipping test.\n");
1530 DestroyWindow(window);
1531 return;
1534 viewport = create_viewport(device, 0, 0, 640, 480);
1535 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1536 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1538 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1539 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1541 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
1542 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1543 hr = IDirect3DDevice3_BeginScene(device);
1544 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1545 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
1546 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1547 hr = IDirect3DDevice3_EndScene(device);
1548 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1550 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1551 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1552 for (i = 0; i < 4; ++i)
1554 for (j = 0; j < 4; ++j)
1556 x = 80 * ((2 * j) + 1);
1557 y = 60 * ((2 * i) + 1);
1558 color = get_surface_color(rt, x, y);
1559 ok(compare_color(color, 0x0000ff00, 1),
1560 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1563 IDirectDrawSurface4_Release(rt);
1565 destroy_viewport(device, viewport);
1566 IDirect3DDevice3_Release(device);
1567 DestroyWindow(window);
1570 static void test_ck_rgba(void)
1572 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1573 static struct
1575 struct vec4 position;
1576 struct vec2 texcoord;
1578 tquad[] =
1580 {{ 0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
1581 {{ 0.0f, 0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
1582 {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
1583 {{640.0f, 0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
1584 {{ 0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
1585 {{ 0.0f, 0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
1586 {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
1587 {{640.0f, 0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
1589 static const struct
1591 D3DCOLOR fill_color;
1592 BOOL color_key;
1593 BOOL blend;
1594 D3DCOLOR result1;
1595 D3DCOLOR result2;
1597 tests[] =
1599 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x000000ff},
1600 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x000000ff},
1601 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00},
1602 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1603 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00807f00},
1604 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x0000ff00},
1605 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00},
1606 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1609 IDirectDrawSurface4 *surface;
1610 IDirect3DViewport3 *viewport;
1611 DDSURFACEDESC2 surface_desc;
1612 IDirect3DTexture2 *texture;
1613 IDirect3DDevice3 *device;
1614 IDirectDrawSurface4 *rt;
1615 IDirectDraw4 *ddraw;
1616 IDirect3D3 *d3d;
1617 D3DCOLOR color;
1618 HWND window;
1619 DDBLTFX fx;
1620 HRESULT hr;
1621 UINT i;
1623 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1624 0, 0, 640, 480, 0, 0, 0, 0);
1625 if (!(device = create_device(window, DDSCL_NORMAL)))
1627 skip("Failed to create a 3D device, skipping test.\n");
1628 DestroyWindow(window);
1629 return;
1632 viewport = create_viewport(device, 0, 0, 640, 480);
1633 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1634 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1636 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1637 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1638 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1639 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1640 IDirect3D3_Release(d3d);
1642 memset(&surface_desc, 0, sizeof(surface_desc));
1643 surface_desc.dwSize = sizeof(surface_desc);
1644 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1645 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1646 surface_desc.dwWidth = 256;
1647 surface_desc.dwHeight = 256;
1648 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1649 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1650 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1651 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1652 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1653 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1654 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1655 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1656 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1657 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1658 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1659 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1660 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1662 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
1663 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1664 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1665 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1666 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1667 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1669 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1670 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1672 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1674 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1675 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1676 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1677 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1679 memset(&fx, 0, sizeof(fx));
1680 fx.dwSize = sizeof(fx);
1681 U5(fx).dwFillColor = tests[i].fill_color;
1682 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1683 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1685 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
1686 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
1687 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1688 hr = IDirect3DDevice3_BeginScene(device);
1689 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1690 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1691 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1692 hr = IDirect3DDevice3_EndScene(device);
1693 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1695 color = get_surface_color(rt, 320, 240);
1696 if (i == 2)
1697 todo_wine ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1698 tests[i].result1, i, color);
1699 else
1700 ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1701 tests[i].result1, i, color);
1703 U5(fx).dwFillColor = 0xff0000ff;
1704 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1705 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1707 hr = IDirect3DDevice3_BeginScene(device);
1708 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1709 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
1710 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1711 hr = IDirect3DDevice3_EndScene(device);
1712 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1714 /* This tests that fragments that are masked out by the color key are
1715 * discarded, instead of just fully transparent. */
1716 color = get_surface_color(rt, 320, 240);
1717 if (i == 2)
1718 todo_wine ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1719 tests[i].result2, i, color);
1720 else
1721 ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1722 tests[i].result2, i, color);
1725 IDirectDrawSurface4_Release(rt);
1726 IDirect3DTexture2_Release(texture);
1727 IDirectDrawSurface4_Release(surface);
1728 destroy_viewport(device, viewport);
1729 IDirectDraw4_Release(ddraw);
1730 IDirect3DDevice3_Release(device);
1731 DestroyWindow(window);
1734 static void test_ck_default(void)
1736 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1737 static struct
1739 struct vec4 position;
1740 struct vec2 texcoord;
1742 tquad[] =
1744 {{ 0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
1745 {{ 0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
1746 {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
1747 {{640.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
1749 IDirectDrawSurface4 *surface, *rt;
1750 IDirect3DViewport3 *viewport;
1751 DDSURFACEDESC2 surface_desc;
1752 IDirect3DTexture2 *texture;
1753 IDirect3DDevice3 *device;
1754 IDirectDraw4 *ddraw;
1755 IDirect3D3 *d3d;
1756 D3DCOLOR color;
1757 DWORD value;
1758 HWND window;
1759 DDBLTFX fx;
1760 HRESULT hr;
1762 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1763 0, 0, 640, 480, 0, 0, 0, 0);
1765 if (!(device = create_device(window, DDSCL_NORMAL)))
1767 skip("Failed to create a 3D device, skipping test.\n");
1768 DestroyWindow(window);
1769 return;
1772 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1773 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1774 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1775 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1776 IDirect3D3_Release(d3d);
1778 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1779 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1781 viewport = create_viewport(device, 0, 0, 640, 480);
1782 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1783 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1785 memset(&surface_desc, 0, sizeof(surface_desc));
1786 surface_desc.dwSize = sizeof(surface_desc);
1787 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1788 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1789 surface_desc.dwWidth = 256;
1790 surface_desc.dwHeight = 256;
1791 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1792 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1793 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1794 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1795 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1796 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1797 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1798 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1799 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1800 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1801 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1802 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1803 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
1804 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1806 memset(&fx, 0, sizeof(fx));
1807 fx.dwSize = sizeof(fx);
1808 U5(fx).dwFillColor = 0x000000ff;
1809 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1810 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1812 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1813 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1814 hr = IDirect3DDevice3_BeginScene(device);
1815 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1816 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1817 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1818 ok(!value, "Got unexpected color keying state %#x.\n", value);
1819 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1820 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1821 hr = IDirect3DDevice3_EndScene(device);
1822 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1823 color = get_surface_color(rt, 320, 240);
1824 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1826 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1827 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1828 hr = IDirect3DDevice3_BeginScene(device);
1829 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1830 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1831 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1832 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1833 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1834 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1835 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1836 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1837 hr = IDirect3DDevice3_EndScene(device);
1838 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1839 color = get_surface_color(rt, 320, 240);
1840 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1842 IDirect3DTexture_Release(texture);
1843 IDirectDrawSurface4_Release(surface);
1844 destroy_viewport(device, viewport);
1845 IDirectDrawSurface4_Release(rt);
1846 IDirect3DDevice3_Release(device);
1847 IDirectDraw4_Release(ddraw);
1848 DestroyWindow(window);
1851 struct qi_test
1853 REFIID iid;
1854 REFIID refcount_iid;
1855 HRESULT hr;
1858 static void test_qi(const char *test_name, IUnknown *base_iface,
1859 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1861 ULONG refcount, expected_refcount;
1862 IUnknown *iface1, *iface2;
1863 HRESULT hr;
1864 UINT i, j;
1866 for (i = 0; i < entry_count; ++i)
1868 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1869 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1870 if (SUCCEEDED(hr))
1872 for (j = 0; j < entry_count; ++j)
1874 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1875 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1876 if (SUCCEEDED(hr))
1878 expected_refcount = 0;
1879 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1880 ++expected_refcount;
1881 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1882 ++expected_refcount;
1883 refcount = IUnknown_Release(iface2);
1884 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1885 refcount, test_name, i, j, expected_refcount);
1889 expected_refcount = 0;
1890 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1891 ++expected_refcount;
1892 refcount = IUnknown_Release(iface1);
1893 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1894 refcount, test_name, i, expected_refcount);
1899 static void test_surface_qi(void)
1901 static const struct qi_test tests[] =
1903 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface4, S_OK },
1904 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface4, S_OK },
1905 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1906 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1907 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1908 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1909 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1910 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1911 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1912 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1913 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1914 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1915 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1916 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1917 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1918 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1919 {&IID_IDirect3D, NULL, E_INVALIDARG },
1920 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1921 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1922 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1923 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1924 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1925 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1926 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1927 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1928 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1929 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1930 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1931 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1932 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1933 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1934 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1935 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1936 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1937 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1940 IDirectDrawSurface4 *surface;
1941 DDSURFACEDESC2 surface_desc;
1942 IDirect3DDevice3 *device;
1943 IDirectDraw4 *ddraw;
1944 HWND window;
1945 HRESULT hr;
1947 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1949 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1950 return;
1953 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1954 0, 0, 640, 480, 0, 0, 0, 0);
1955 /* Try to create a D3D device to see if the ddraw implementation supports
1956 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1957 * doesn't support e.g. the IDirect3DTexture interfaces. */
1958 if (!(device = create_device(window, DDSCL_NORMAL)))
1960 skip("Failed to create a 3D device, skipping test.\n");
1961 DestroyWindow(window);
1962 return;
1964 IDirect3DDevice_Release(device);
1965 if (!(ddraw = create_ddraw()))
1967 skip("Failed to create a ddraw object, skipping test.\n");
1968 DestroyWindow(window);
1969 return;
1971 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1972 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1974 memset(&surface_desc, 0, sizeof(surface_desc));
1975 surface_desc.dwSize = sizeof(surface_desc);
1976 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1977 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1978 surface_desc.dwWidth = 512;
1979 surface_desc.dwHeight = 512;
1980 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1981 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1983 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface4, tests, sizeof(tests) / sizeof(*tests));
1985 IDirectDrawSurface4_Release(surface);
1986 IDirectDraw4_Release(ddraw);
1987 DestroyWindow(window);
1990 static void test_device_qi(void)
1992 static const struct qi_test tests[] =
1994 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
1995 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
1996 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
1997 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1998 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
1999 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2000 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2001 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2002 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2003 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
2004 {&IID_IDirect3DDevice3, &IID_IDirect3DDevice3, S_OK },
2005 {&IID_IDirect3DDevice2, &IID_IDirect3DDevice3, S_OK },
2006 {&IID_IDirect3DDevice, &IID_IDirect3DDevice3, S_OK },
2007 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2008 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2009 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2010 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2011 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2012 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2013 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2014 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2015 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2016 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2017 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2018 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2019 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2020 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2021 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2022 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2023 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2024 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2025 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2026 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2027 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2028 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2029 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2030 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2031 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2032 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2033 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2034 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2035 {&IID_IUnknown, &IID_IDirect3DDevice3, S_OK },
2038 IDirect3DDevice3 *device;
2039 HWND window;
2041 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2042 0, 0, 640, 480, 0, 0, 0, 0);
2043 if (!(device = create_device(window, DDSCL_NORMAL)))
2045 skip("Failed to create a 3D device, skipping test.\n");
2046 DestroyWindow(window);
2047 return;
2050 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice3, tests, sizeof(tests) / sizeof(*tests));
2052 IDirect3DDevice3_Release(device);
2053 DestroyWindow(window);
2056 static void test_wndproc(void)
2058 LONG_PTR proc, ddraw_proc;
2059 IDirectDraw4 *ddraw;
2060 WNDCLASSA wc = {0};
2061 HWND window;
2062 HRESULT hr;
2063 ULONG ref;
2065 static const UINT messages[] =
2067 WM_WINDOWPOSCHANGING,
2068 WM_MOVE,
2069 WM_SIZE,
2070 WM_WINDOWPOSCHANGING,
2071 WM_ACTIVATE,
2072 WM_SETFOCUS,
2076 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2077 if (!(ddraw = create_ddraw()))
2079 skip("Failed to create a ddraw object, skipping test.\n");
2080 return;
2083 wc.lpfnWndProc = test_proc;
2084 wc.lpszClassName = "ddraw_test_wndproc_wc";
2085 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2087 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2088 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2090 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2091 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2092 (LONG_PTR)test_proc, proc);
2093 expect_messages = messages;
2094 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2095 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2096 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2097 expect_messages = NULL;
2098 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2099 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2100 (LONG_PTR)test_proc, proc);
2101 ref = IDirectDraw4_Release(ddraw);
2102 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2103 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2104 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2105 (LONG_PTR)test_proc, proc);
2107 /* DDSCL_NORMAL doesn't. */
2108 ddraw = create_ddraw();
2109 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2110 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2111 (LONG_PTR)test_proc, proc);
2112 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2113 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2114 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2115 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2116 (LONG_PTR)test_proc, proc);
2117 ref = IDirectDraw4_Release(ddraw);
2118 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2119 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2120 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2121 (LONG_PTR)test_proc, proc);
2123 /* The original window proc is only restored by ddraw if the current
2124 * window proc matches the one ddraw set. This also affects switching
2125 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2126 ddraw = create_ddraw();
2127 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2128 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2129 (LONG_PTR)test_proc, proc);
2130 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2131 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2132 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2133 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2134 (LONG_PTR)test_proc, proc);
2135 ddraw_proc = proc;
2136 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2137 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2138 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2139 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2140 (LONG_PTR)test_proc, proc);
2141 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2142 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2143 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2144 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2145 (LONG_PTR)test_proc, proc);
2146 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2147 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2148 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2149 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2150 (LONG_PTR)DefWindowProcA, proc);
2151 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2152 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2153 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
2154 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2155 (LONG_PTR)DefWindowProcA, proc);
2156 ref = IDirectDraw4_Release(ddraw);
2157 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2158 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2159 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2160 (LONG_PTR)test_proc, proc);
2162 ddraw = create_ddraw();
2163 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2164 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2165 (LONG_PTR)test_proc, proc);
2166 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2167 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2168 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2169 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2170 (LONG_PTR)test_proc, proc);
2171 ref = IDirectDraw4_Release(ddraw);
2172 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2173 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2174 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2175 (LONG_PTR)DefWindowProcA, proc);
2177 fix_wndproc(window, (LONG_PTR)test_proc);
2178 expect_messages = NULL;
2179 DestroyWindow(window);
2180 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2183 static void test_window_style(void)
2185 LONG style, exstyle, tmp;
2186 RECT fullscreen_rect, r;
2187 IDirectDraw4 *ddraw;
2188 HWND window;
2189 HRESULT hr;
2190 ULONG ref;
2192 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2193 0, 0, 100, 100, 0, 0, 0, 0);
2194 if (!(ddraw = create_ddraw()))
2196 skip("Failed to create a ddraw object, skipping test.\n");
2197 DestroyWindow(window);
2198 return;
2201 style = GetWindowLongA(window, GWL_STYLE);
2202 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2203 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2205 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2206 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2208 tmp = GetWindowLongA(window, GWL_STYLE);
2209 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2210 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2211 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2213 GetWindowRect(window, &r);
2214 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2215 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2216 r.left, r.top, r.right, r.bottom);
2217 GetClientRect(window, &r);
2218 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2220 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2221 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2223 tmp = GetWindowLongA(window, GWL_STYLE);
2224 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2225 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2226 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2228 ref = IDirectDraw4_Release(ddraw);
2229 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2231 DestroyWindow(window);
2234 static void test_redundant_mode_set(void)
2236 DDSURFACEDESC2 surface_desc = {0};
2237 IDirectDraw4 *ddraw;
2238 HWND window;
2239 HRESULT hr;
2240 RECT r, s;
2241 ULONG ref;
2243 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2244 0, 0, 100, 100, 0, 0, 0, 0);
2245 if (!(ddraw = create_ddraw()))
2247 skip("Failed to create a ddraw object, skipping test.\n");
2248 DestroyWindow(window);
2249 return;
2252 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2253 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2255 surface_desc.dwSize = sizeof(surface_desc);
2256 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
2257 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
2259 hr = IDirectDraw4_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2260 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2261 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2263 GetWindowRect(window, &r);
2264 r.right /= 2;
2265 r.bottom /= 2;
2266 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2267 GetWindowRect(window, &s);
2268 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2269 r.left, r.top, r.right, r.bottom,
2270 s.left, s.top, s.right, s.bottom);
2272 hr = IDirectDraw4_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2273 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2274 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2276 GetWindowRect(window, &s);
2277 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2278 r.left, r.top, r.right, r.bottom,
2279 s.left, s.top, s.right, s.bottom);
2281 ref = IDirectDraw4_Release(ddraw);
2282 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2284 DestroyWindow(window);
2287 static SIZE screen_size, screen_size2;
2289 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2291 if (message == WM_SIZE)
2293 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2294 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2297 return test_proc(hwnd, message, wparam, lparam);
2300 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2302 if (message == WM_SIZE)
2304 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2305 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2308 return test_proc(hwnd, message, wparam, lparam);
2311 static void test_coop_level_mode_set(void)
2313 IDirectDrawSurface4 *primary;
2314 RECT fullscreen_rect, r, s;
2315 IDirectDraw4 *ddraw;
2316 DDSURFACEDESC2 ddsd;
2317 WNDCLASSA wc = {0};
2318 HWND window, window2;
2319 HRESULT hr;
2320 ULONG ref;
2322 static const UINT exclusive_messages[] =
2324 WM_WINDOWPOSCHANGING,
2325 WM_WINDOWPOSCHANGED,
2326 WM_SIZE,
2327 WM_DISPLAYCHANGE,
2331 static const UINT normal_messages[] =
2333 WM_DISPLAYCHANGE,
2337 if (!(ddraw = create_ddraw()))
2339 skip("Failed to create a ddraw object, skipping test.\n");
2340 return;
2343 wc.lpfnWndProc = mode_set_proc;
2344 wc.lpszClassName = "ddraw_test_wndproc_wc";
2345 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2346 wc.lpfnWndProc = mode_set_proc2;
2347 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2348 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2350 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2351 0, 0, 100, 100, 0, 0, 0, 0);
2352 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2353 0, 0, 100, 100, 0, 0, 0, 0);
2355 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2356 SetRect(&s, 0, 0, 640, 480);
2358 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2359 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2361 GetWindowRect(window, &r);
2362 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2363 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2364 r.left, r.top, r.right, r.bottom);
2366 memset(&ddsd, 0, sizeof(ddsd));
2367 ddsd.dwSize = sizeof(ddsd);
2368 ddsd.dwFlags = DDSD_CAPS;
2369 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2371 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2372 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2373 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2374 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2375 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2376 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2377 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2378 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2380 GetWindowRect(window, &r);
2381 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2382 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2383 r.left, r.top, r.right, r.bottom);
2385 expect_messages = exclusive_messages;
2386 screen_size.cx = 0;
2387 screen_size.cy = 0;
2389 hr = IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2390 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2392 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2393 expect_messages = NULL;
2394 ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
2395 "Expected screen size %ux%u, got %ux%u.\n",
2396 s.right, s.bottom, screen_size.cx, screen_size.cy);
2398 GetWindowRect(window, &r);
2399 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2400 s.left, s.top, s.right, s.bottom,
2401 r.left, r.top, r.right, r.bottom);
2403 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2404 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2405 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2406 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2407 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2408 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2409 IDirectDrawSurface4_Release(primary);
2411 memset(&ddsd, 0, sizeof(ddsd));
2412 ddsd.dwSize = sizeof(ddsd);
2413 ddsd.dwFlags = DDSD_CAPS;
2414 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2416 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2417 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2418 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2419 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2420 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2421 s.right - s.left, ddsd.dwWidth);
2422 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2423 s.bottom - s.top, ddsd.dwHeight);
2425 GetWindowRect(window, &r);
2426 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2427 s.left, s.top, s.right, s.bottom,
2428 r.left, r.top, r.right, r.bottom);
2430 expect_messages = exclusive_messages;
2431 screen_size.cx = 0;
2432 screen_size.cy = 0;
2434 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2435 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2437 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2438 expect_messages = NULL;
2439 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2440 "Expected screen size %ux%u, got %ux%u.\n",
2441 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2443 GetWindowRect(window, &r);
2444 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2445 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2446 r.left, r.top, r.right, r.bottom);
2448 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2449 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2450 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2451 s.right - s.left, ddsd.dwWidth);
2452 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2453 s.bottom - s.top, ddsd.dwHeight);
2454 IDirectDrawSurface4_Release(primary);
2456 memset(&ddsd, 0, sizeof(ddsd));
2457 ddsd.dwSize = sizeof(ddsd);
2458 ddsd.dwFlags = DDSD_CAPS;
2459 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2461 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2462 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2463 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2464 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2465 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2466 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2467 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2468 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2470 GetWindowRect(window, &r);
2471 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2472 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2473 r.left, r.top, r.right, r.bottom);
2475 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2476 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2478 GetWindowRect(window, &r);
2479 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2480 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2481 r.left, r.top, r.right, r.bottom);
2483 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2484 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2485 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2486 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2487 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2488 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2489 IDirectDrawSurface4_Release(primary);
2491 memset(&ddsd, 0, sizeof(ddsd));
2492 ddsd.dwSize = sizeof(ddsd);
2493 ddsd.dwFlags = DDSD_CAPS;
2494 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2496 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2497 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2498 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2499 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2500 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2501 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2502 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2503 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2505 GetWindowRect(window, &r);
2506 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2507 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2508 r.left, r.top, r.right, r.bottom);
2510 expect_messages = normal_messages;
2511 screen_size.cx = 0;
2512 screen_size.cy = 0;
2514 hr = IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2515 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2517 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2518 expect_messages = NULL;
2519 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2521 GetWindowRect(window, &r);
2522 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2523 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2524 r.left, r.top, r.right, r.bottom);
2526 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2527 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2528 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2529 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2530 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2531 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2532 IDirectDrawSurface4_Release(primary);
2534 memset(&ddsd, 0, sizeof(ddsd));
2535 ddsd.dwSize = sizeof(ddsd);
2536 ddsd.dwFlags = DDSD_CAPS;
2537 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2539 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2540 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2541 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2542 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2543 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2544 s.right - s.left, ddsd.dwWidth);
2545 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2546 s.bottom - s.top, ddsd.dwHeight);
2548 GetWindowRect(window, &r);
2549 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2550 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2551 r.left, r.top, r.right, r.bottom);
2553 expect_messages = normal_messages;
2554 screen_size.cx = 0;
2555 screen_size.cy = 0;
2557 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2558 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2560 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2561 expect_messages = NULL;
2562 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2564 GetWindowRect(window, &r);
2565 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2566 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2567 r.left, r.top, r.right, r.bottom);
2569 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2570 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2571 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2572 s.right - s.left, ddsd.dwWidth);
2573 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2574 s.bottom - s.top, ddsd.dwHeight);
2575 IDirectDrawSurface4_Release(primary);
2577 memset(&ddsd, 0, sizeof(ddsd));
2578 ddsd.dwSize = sizeof(ddsd);
2579 ddsd.dwFlags = DDSD_CAPS;
2580 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2582 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2583 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2584 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2585 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2586 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2587 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2588 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2589 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2591 GetWindowRect(window, &r);
2592 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2593 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2594 r.left, r.top, r.right, r.bottom);
2596 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2597 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2598 * not DDSCL_FULLSCREEN. */
2599 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2600 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2602 GetWindowRect(window, &r);
2603 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2604 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2605 r.left, r.top, r.right, r.bottom);
2607 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2608 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2609 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2610 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2611 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2612 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2613 IDirectDrawSurface4_Release(primary);
2615 memset(&ddsd, 0, sizeof(ddsd));
2616 ddsd.dwSize = sizeof(ddsd);
2617 ddsd.dwFlags = DDSD_CAPS;
2618 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2620 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2621 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2622 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2623 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2624 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2625 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2626 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2627 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2629 GetWindowRect(window, &r);
2630 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2631 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2632 r.left, r.top, r.right, r.bottom);
2634 expect_messages = normal_messages;
2635 screen_size.cx = 0;
2636 screen_size.cy = 0;
2638 hr = IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2639 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2641 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2642 expect_messages = NULL;
2643 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2645 GetWindowRect(window, &r);
2646 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2647 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2648 r.left, r.top, r.right, r.bottom);
2650 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2651 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2652 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2653 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2654 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2655 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2656 IDirectDrawSurface4_Release(primary);
2658 memset(&ddsd, 0, sizeof(ddsd));
2659 ddsd.dwSize = sizeof(ddsd);
2660 ddsd.dwFlags = DDSD_CAPS;
2661 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2663 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2664 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2665 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2666 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2667 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2668 s.right - s.left, ddsd.dwWidth);
2669 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2670 s.bottom - s.top, ddsd.dwHeight);
2672 GetWindowRect(window, &r);
2673 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2674 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2675 r.left, r.top, r.right, r.bottom);
2677 expect_messages = normal_messages;
2678 screen_size.cx = 0;
2679 screen_size.cy = 0;
2681 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2682 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2684 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2685 expect_messages = NULL;
2686 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2688 GetWindowRect(window, &r);
2689 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2690 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2691 r.left, r.top, r.right, r.bottom);
2693 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2694 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2695 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2696 s.right - s.left, ddsd.dwWidth);
2697 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2698 s.bottom - s.top, ddsd.dwHeight);
2699 IDirectDrawSurface4_Release(primary);
2701 memset(&ddsd, 0, sizeof(ddsd));
2702 ddsd.dwSize = sizeof(ddsd);
2703 ddsd.dwFlags = DDSD_CAPS;
2704 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2706 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2707 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2708 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2709 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2710 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2711 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2712 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2713 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2714 IDirectDrawSurface4_Release(primary);
2716 GetWindowRect(window, &r);
2717 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2718 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2719 r.left, r.top, r.right, r.bottom);
2721 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
2722 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2723 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2724 hr = IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2725 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2727 expect_messages = exclusive_messages;
2728 screen_size.cx = 0;
2729 screen_size.cy = 0;
2731 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2732 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2734 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2735 expect_messages = NULL;
2736 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2737 "Expected screen size %ux%u, got %ux%u.\n",
2738 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2740 GetWindowRect(window, &r);
2741 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2742 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2743 r.left, r.top, r.right, r.bottom);
2745 memset(&ddsd, 0, sizeof(ddsd));
2746 ddsd.dwSize = sizeof(ddsd);
2747 ddsd.dwFlags = DDSD_CAPS;
2748 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2750 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2751 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2752 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2753 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2754 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2755 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2756 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2757 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2758 IDirectDrawSurface_Release(primary);
2760 /* The screen restore is a property of DDSCL_EXCLUSIVE */
2761 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2762 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2763 hr = IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2764 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2766 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2767 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2769 memset(&ddsd, 0, sizeof(ddsd));
2770 ddsd.dwSize = sizeof(ddsd);
2771 ddsd.dwFlags = DDSD_CAPS;
2772 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2774 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2775 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2776 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2777 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2778 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2779 s.right - s.left, ddsd.dwWidth);
2780 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2781 s.bottom - s.top, ddsd.dwHeight);
2782 IDirectDrawSurface_Release(primary);
2784 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2785 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2787 /* If the window is changed at the same time, messages are sent to the new window. */
2788 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2789 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2790 hr = IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2791 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2793 expect_messages = exclusive_messages;
2794 screen_size.cx = 0;
2795 screen_size.cy = 0;
2796 screen_size2.cx = 0;
2797 screen_size2.cy = 0;
2799 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
2800 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2802 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2803 expect_messages = NULL;
2804 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n",
2805 screen_size.cx, screen_size.cy);
2806 ok(screen_size2.cx == fullscreen_rect.right && screen_size2.cy == fullscreen_rect.bottom,
2807 "Expected screen size 2 %ux%u, got %ux%u.\n",
2808 fullscreen_rect.right, fullscreen_rect.bottom, screen_size2.cx, screen_size2.cy);
2810 GetWindowRect(window, &r);
2811 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2812 s.left, s.top, s.right, s.bottom,
2813 r.left, r.top, r.right, r.bottom);
2814 GetWindowRect(window2, &r);
2815 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2816 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2817 r.left, r.top, r.right, r.bottom);
2819 memset(&ddsd, 0, sizeof(ddsd));
2820 ddsd.dwSize = sizeof(ddsd);
2821 ddsd.dwFlags = DDSD_CAPS;
2822 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2824 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2825 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2826 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2827 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2828 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2829 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2830 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2831 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2832 IDirectDrawSurface_Release(primary);
2834 ref = IDirectDraw4_Release(ddraw);
2835 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2837 GetWindowRect(window, &r);
2838 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2839 s.left, s.top, s.right, s.bottom,
2840 r.left, r.top, r.right, r.bottom);
2842 expect_messages = NULL;
2843 DestroyWindow(window);
2844 DestroyWindow(window2);
2845 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2846 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
2849 static void test_coop_level_mode_set_multi(void)
2851 IDirectDraw4 *ddraw1, *ddraw2;
2852 UINT orig_w, orig_h, w, h;
2853 HWND window;
2854 HRESULT hr;
2855 ULONG ref;
2857 if (!(ddraw1 = create_ddraw()))
2859 skip("Failed to create a ddraw object, skipping test.\n");
2860 return;
2863 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2864 0, 0, 100, 100, 0, 0, 0, 0);
2866 orig_w = GetSystemMetrics(SM_CXSCREEN);
2867 orig_h = GetSystemMetrics(SM_CYSCREEN);
2869 /* With just a single ddraw object, the display mode is restored on
2870 * release. */
2871 hr = IDirectDraw4_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2872 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2873 w = GetSystemMetrics(SM_CXSCREEN);
2874 ok(w == 800, "Got unexpected screen width %u.\n", w);
2875 h = GetSystemMetrics(SM_CYSCREEN);
2876 ok(h == 600, "Got unexpected screen height %u.\n", h);
2878 ref = IDirectDraw4_Release(ddraw1);
2879 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2880 w = GetSystemMetrics(SM_CXSCREEN);
2881 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2882 h = GetSystemMetrics(SM_CYSCREEN);
2883 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2885 /* When there are multiple ddraw objects, the display mode is restored to
2886 * the initial mode, before the first SetDisplayMode() call. */
2887 ddraw1 = create_ddraw();
2888 hr = IDirectDraw4_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2889 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2890 w = GetSystemMetrics(SM_CXSCREEN);
2891 ok(w == 800, "Got unexpected screen width %u.\n", w);
2892 h = GetSystemMetrics(SM_CYSCREEN);
2893 ok(h == 600, "Got unexpected screen height %u.\n", h);
2895 ddraw2 = create_ddraw();
2896 hr = IDirectDraw4_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2897 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2898 w = GetSystemMetrics(SM_CXSCREEN);
2899 ok(w == 640, "Got unexpected screen width %u.\n", w);
2900 h = GetSystemMetrics(SM_CYSCREEN);
2901 ok(h == 480, "Got unexpected screen height %u.\n", h);
2903 ref = IDirectDraw4_Release(ddraw2);
2904 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2905 w = GetSystemMetrics(SM_CXSCREEN);
2906 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2907 h = GetSystemMetrics(SM_CYSCREEN);
2908 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2910 ref = IDirectDraw4_Release(ddraw1);
2911 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2912 w = GetSystemMetrics(SM_CXSCREEN);
2913 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2914 h = GetSystemMetrics(SM_CYSCREEN);
2915 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2917 /* Regardless of release ordering. */
2918 ddraw1 = create_ddraw();
2919 hr = IDirectDraw4_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2920 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2921 w = GetSystemMetrics(SM_CXSCREEN);
2922 ok(w == 800, "Got unexpected screen width %u.\n", w);
2923 h = GetSystemMetrics(SM_CYSCREEN);
2924 ok(h == 600, "Got unexpected screen height %u.\n", h);
2926 ddraw2 = create_ddraw();
2927 hr = IDirectDraw4_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2928 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2929 w = GetSystemMetrics(SM_CXSCREEN);
2930 ok(w == 640, "Got unexpected screen width %u.\n", w);
2931 h = GetSystemMetrics(SM_CYSCREEN);
2932 ok(h == 480, "Got unexpected screen height %u.\n", h);
2934 ref = IDirectDraw4_Release(ddraw1);
2935 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2936 w = GetSystemMetrics(SM_CXSCREEN);
2937 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2938 h = GetSystemMetrics(SM_CYSCREEN);
2939 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2941 ref = IDirectDraw4_Release(ddraw2);
2942 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2943 w = GetSystemMetrics(SM_CXSCREEN);
2944 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2945 h = GetSystemMetrics(SM_CYSCREEN);
2946 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2948 /* But only for ddraw objects that called SetDisplayMode(). */
2949 ddraw1 = create_ddraw();
2950 ddraw2 = create_ddraw();
2951 hr = IDirectDraw4_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2952 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2953 w = GetSystemMetrics(SM_CXSCREEN);
2954 ok(w == 640, "Got unexpected screen width %u.\n", w);
2955 h = GetSystemMetrics(SM_CYSCREEN);
2956 ok(h == 480, "Got unexpected screen height %u.\n", h);
2958 ref = IDirectDraw4_Release(ddraw1);
2959 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2960 w = GetSystemMetrics(SM_CXSCREEN);
2961 ok(w == 640, "Got unexpected screen width %u.\n", w);
2962 h = GetSystemMetrics(SM_CYSCREEN);
2963 ok(h == 480, "Got unexpected screen height %u.\n", h);
2965 ref = IDirectDraw4_Release(ddraw2);
2966 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2967 w = GetSystemMetrics(SM_CXSCREEN);
2968 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2969 h = GetSystemMetrics(SM_CYSCREEN);
2970 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2972 /* If there's a ddraw object that's currently in exclusive mode, it blocks
2973 * restoring the display mode. */
2974 ddraw1 = create_ddraw();
2975 hr = IDirectDraw4_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2976 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2977 w = GetSystemMetrics(SM_CXSCREEN);
2978 ok(w == 800, "Got unexpected screen width %u.\n", w);
2979 h = GetSystemMetrics(SM_CYSCREEN);
2980 ok(h == 600, "Got unexpected screen height %u.\n", h);
2982 ddraw2 = create_ddraw();
2983 hr = IDirectDraw4_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2984 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2985 w = GetSystemMetrics(SM_CXSCREEN);
2986 ok(w == 640, "Got unexpected screen width %u.\n", w);
2987 h = GetSystemMetrics(SM_CYSCREEN);
2988 ok(h == 480, "Got unexpected screen height %u.\n", h);
2990 hr = IDirectDraw4_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2991 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2993 ref = IDirectDraw4_Release(ddraw1);
2994 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2995 w = GetSystemMetrics(SM_CXSCREEN);
2996 ok(w == 640, "Got unexpected screen width %u.\n", w);
2997 h = GetSystemMetrics(SM_CYSCREEN);
2998 ok(h == 480, "Got unexpected screen height %u.\n", h);
3000 ref = IDirectDraw4_Release(ddraw2);
3001 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3002 w = GetSystemMetrics(SM_CXSCREEN);
3003 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
3004 h = GetSystemMetrics(SM_CYSCREEN);
3005 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
3007 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3008 ddraw1 = create_ddraw();
3009 hr = IDirectDraw4_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
3010 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
3011 w = GetSystemMetrics(SM_CXSCREEN);
3012 ok(w == 800, "Got unexpected screen width %u.\n", w);
3013 h = GetSystemMetrics(SM_CYSCREEN);
3014 ok(h == 600, "Got unexpected screen height %u.\n", h);
3016 hr = IDirectDraw4_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3017 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3019 ddraw2 = create_ddraw();
3020 hr = IDirectDraw4_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
3021 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3023 ref = IDirectDraw4_Release(ddraw1);
3024 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3025 w = GetSystemMetrics(SM_CXSCREEN);
3026 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
3027 h = GetSystemMetrics(SM_CYSCREEN);
3028 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
3030 ref = IDirectDraw4_Release(ddraw2);
3031 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3032 w = GetSystemMetrics(SM_CXSCREEN);
3033 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
3034 h = GetSystemMetrics(SM_CYSCREEN);
3035 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
3037 DestroyWindow(window);
3040 static void test_initialize(void)
3042 IDirectDraw4 *ddraw;
3043 HRESULT hr;
3045 if (!(ddraw = create_ddraw()))
3047 skip("Failed to create a ddraw object, skipping test.\n");
3048 return;
3051 hr = IDirectDraw4_Initialize(ddraw, NULL);
3052 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3053 IDirectDraw4_Release(ddraw);
3055 CoInitialize(NULL);
3056 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw4, (void **)&ddraw);
3057 ok(SUCCEEDED(hr), "Failed to create IDirectDraw4 instance, hr %#x.\n", hr);
3058 hr = IDirectDraw4_Initialize(ddraw, NULL);
3059 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3060 hr = IDirectDraw4_Initialize(ddraw, NULL);
3061 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3062 IDirectDraw4_Release(ddraw);
3063 CoUninitialize();
3066 static void test_coop_level_surf_create(void)
3068 IDirectDrawSurface4 *surface;
3069 IDirectDraw4 *ddraw;
3070 DDSURFACEDESC2 ddsd;
3071 HRESULT hr;
3073 if (!(ddraw = create_ddraw()))
3075 skip("Failed to create a ddraw object, skipping test.\n");
3076 return;
3079 memset(&ddsd, 0, sizeof(ddsd));
3080 ddsd.dwSize = sizeof(ddsd);
3081 ddsd.dwFlags = DDSD_CAPS;
3082 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3083 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
3084 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3086 IDirectDraw4_Release(ddraw);
3089 static void test_vb_discard(void)
3091 static const struct vec4 quad[] =
3093 { 0.0f, 480.0f, 0.0f, 1.0f},
3094 { 0.0f, 0.0f, 0.0f, 1.0f},
3095 {640.0f, 480.0f, 0.0f, 1.0f},
3096 {640.0f, 0.0f, 0.0f, 1.0f},
3099 IDirect3DDevice3 *device;
3100 IDirect3D3 *d3d;
3101 IDirect3DVertexBuffer *buffer;
3102 HWND window;
3103 HRESULT hr;
3104 D3DVERTEXBUFFERDESC desc;
3105 BYTE *data;
3106 static const unsigned int vbsize = 16;
3107 unsigned int i;
3109 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3110 0, 0, 640, 480, 0, 0, 0, 0);
3112 if (!(device = create_device(window, DDSCL_NORMAL)))
3114 skip("Failed to create a 3D device, skipping test.\n");
3115 DestroyWindow(window);
3116 return;
3119 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
3120 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
3122 memset(&desc, 0, sizeof(desc));
3123 desc.dwSize = sizeof(desc);
3124 desc.dwCaps = D3DVBCAPS_WRITEONLY;
3125 desc.dwFVF = D3DFVF_XYZRHW;
3126 desc.dwNumVertices = vbsize;
3127 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &buffer, 0, NULL);
3128 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3130 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3131 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3132 memcpy(data, quad, sizeof(quad));
3133 hr = IDirect3DVertexBuffer_Unlock(buffer);
3134 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3136 hr = IDirect3DDevice3_BeginScene(device);
3137 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3138 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
3139 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3140 hr = IDirect3DDevice3_EndScene(device);
3141 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3143 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3144 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3145 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
3146 hr = IDirect3DVertexBuffer_Unlock(buffer);
3147 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3149 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3150 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3151 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
3153 if (data[i] != 0xaa)
3155 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
3156 break;
3159 hr = IDirect3DVertexBuffer_Unlock(buffer);
3160 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3162 IDirect3DVertexBuffer_Release(buffer);
3163 IDirect3D3_Release(d3d);
3164 IDirect3DDevice3_Release(device);
3165 DestroyWindow(window);
3168 static void test_coop_level_multi_window(void)
3170 HWND window1, window2;
3171 IDirectDraw4 *ddraw;
3172 HRESULT hr;
3174 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3175 0, 0, 640, 480, 0, 0, 0, 0);
3176 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
3177 0, 0, 640, 480, 0, 0, 0, 0);
3178 if (!(ddraw = create_ddraw()))
3180 skip("Failed to create a ddraw object, skipping test.\n");
3181 DestroyWindow(window2);
3182 DestroyWindow(window1);
3183 return;
3186 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3187 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3188 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3189 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3190 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3191 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3193 IDirectDraw4_Release(ddraw);
3194 DestroyWindow(window2);
3195 DestroyWindow(window1);
3198 static void test_draw_strided(void)
3200 static struct vec3 position[] =
3202 {-1.0, -1.0, 0.0},
3203 {-1.0, 1.0, 0.0},
3204 { 1.0, 1.0, 0.0},
3205 { 1.0, -1.0, 0.0},
3207 static DWORD diffuse[] =
3209 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
3211 static WORD indices[] =
3213 0, 1, 2, 2, 3, 0
3216 IDirectDrawSurface4 *rt;
3217 IDirect3DDevice3 *device;
3218 D3DCOLOR color;
3219 HWND window;
3220 HRESULT hr;
3221 D3DDRAWPRIMITIVESTRIDEDDATA strided;
3222 IDirect3DViewport3 *viewport;
3223 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3225 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3226 0, 0, 640, 480, 0, 0, 0, 0);
3228 if (!(device = create_device(window, DDSCL_NORMAL)))
3230 skip("Failed to create a 3D device, skipping test.\n");
3231 DestroyWindow(window);
3232 return;
3235 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
3236 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3237 viewport = create_viewport(device, 0, 0, 640, 480);
3238 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
3239 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
3240 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
3241 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3243 hr = IDirect3DDevice3_BeginScene(device);
3244 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3246 memset(&strided, 0x55, sizeof(strided));
3247 strided.position.lpvData = position;
3248 strided.position.dwStride = sizeof(*position);
3249 strided.diffuse.lpvData = diffuse;
3250 strided.diffuse.dwStride = sizeof(*diffuse);
3251 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3252 &strided, 4, indices, 6, 0);
3253 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3255 hr = IDirect3DDevice3_EndScene(device);
3256 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3258 color = get_surface_color(rt, 320, 240);
3259 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3261 IDirect3DViewport3_Release(viewport);
3262 IDirectDrawSurface4_Release(rt);
3263 IDirect3DDevice3_Release(device);
3264 DestroyWindow(window);
3267 static void test_clear_rect_count(void)
3269 IDirectDrawSurface4 *rt;
3270 IDirect3DDevice3 *device;
3271 D3DCOLOR color;
3272 HWND window;
3273 HRESULT hr;
3274 IDirect3DViewport3 *viewport;
3275 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3277 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3278 0, 0, 640, 480, 0, 0, 0, 0);
3279 if (!(device = create_device(window, DDSCL_NORMAL)))
3281 skip("Failed to create a 3D device, skipping test.\n");
3282 DestroyWindow(window);
3283 return;
3286 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
3287 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3289 viewport = create_viewport(device, 0, 0, 640, 480);
3290 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
3291 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
3292 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00ffffff, 0.0f, 0);
3293 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3294 hr = IDirect3DViewport3_Clear2(viewport, 0, &clear_rect, D3DCLEAR_TARGET, 0x00ff0000, 0.0f, 0);
3295 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3296 hr = IDirect3DViewport3_Clear2(viewport, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 0.0f, 0);
3297 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3298 hr = IDirect3DViewport3_Clear2(viewport, 1, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
3299 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3301 color = get_surface_color(rt, 320, 240);
3302 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
3304 IDirect3DViewport3_Release(viewport);
3305 IDirectDrawSurface4_Release(rt);
3306 IDirect3DDevice3_Release(device);
3307 DestroyWindow(window);
3310 static BOOL test_mode_restored(IDirectDraw4 *ddraw, HWND window)
3312 DDSURFACEDESC2 ddsd1, ddsd2;
3313 HRESULT hr;
3315 memset(&ddsd1, 0, sizeof(ddsd1));
3316 ddsd1.dwSize = sizeof(ddsd1);
3317 hr = IDirectDraw4_GetDisplayMode(ddraw, &ddsd1);
3318 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
3320 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3321 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3322 hr = IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
3323 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
3324 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3325 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3327 memset(&ddsd2, 0, sizeof(ddsd2));
3328 ddsd2.dwSize = sizeof(ddsd2);
3329 hr = IDirectDraw4_GetDisplayMode(ddraw, &ddsd2);
3330 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
3331 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3332 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3334 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
3337 static void test_coop_level_versions(void)
3339 HWND window;
3340 IDirectDraw *ddraw;
3341 HRESULT hr;
3342 BOOL restored;
3343 IDirectDrawSurface *surface;
3344 IDirectDraw4 *ddraw4;
3345 DDSURFACEDESC ddsd;
3347 window = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3348 0, 0, 640, 480, 0, 0, 0, 0);
3350 if (!(ddraw4 = create_ddraw()))
3351 goto done;
3352 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
3353 restored = test_mode_restored(ddraw4, window);
3354 ok(restored, "Display mode not restored in new ddraw object\n");
3356 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
3357 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
3358 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3360 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3361 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
3362 restored = test_mode_restored(ddraw4, window);
3363 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
3365 /* A successful one does */
3366 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3367 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3368 restored = test_mode_restored(ddraw4, window);
3369 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
3371 IDirectDraw_Release(ddraw);
3372 IDirectDraw4_Release(ddraw4);
3374 if (!(ddraw4 = create_ddraw()))
3375 goto done;
3376 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
3377 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3379 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
3380 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3381 restored = test_mode_restored(ddraw4, window);
3382 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
3384 IDirectDraw_Release(ddraw);
3385 IDirectDraw4_Release(ddraw4);
3387 /* A failing call does not restore the ddraw2+ behavior */
3388 if (!(ddraw4 = create_ddraw()))
3389 goto done;
3390 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
3391 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3393 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3394 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3395 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3396 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
3397 restored = test_mode_restored(ddraw4, window);
3398 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
3400 IDirectDraw_Release(ddraw);
3401 IDirectDraw4_Release(ddraw4);
3403 /* Neither does a sequence of successful calls with the new interface */
3404 if (!(ddraw4 = create_ddraw()))
3405 goto done;
3406 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
3407 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3409 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3410 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3411 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3412 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3413 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_NORMAL);
3414 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3416 restored = test_mode_restored(ddraw4, window);
3417 ok(!restored, "Display mode restored after ddraw1-ddraw4 SetCooperativeLevel() call sequence\n");
3418 IDirectDraw_Release(ddraw);
3419 IDirectDraw4_Release(ddraw4);
3421 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
3422 if (!(ddraw4 = create_ddraw()))
3423 goto done;
3424 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
3425 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3427 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_NORMAL);
3428 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3430 memset(&ddsd, 0, sizeof(ddsd));
3431 ddsd.dwSize = sizeof(ddsd);
3432 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
3433 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3434 ddsd.dwWidth = ddsd.dwHeight = 8;
3435 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3436 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
3437 IDirectDrawSurface_Release(surface);
3438 restored = test_mode_restored(ddraw4, window);
3439 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
3441 IDirectDraw_Release(ddraw);
3442 IDirectDraw4_Release(ddraw4);
3444 done:
3445 DestroyWindow(window);
3448 static void test_lighting_interface_versions(void)
3450 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3451 IDirect3DMaterial3 *emissive;
3452 IDirect3DViewport3 *viewport;
3453 IDirect3DDevice3 *device;
3454 IDirectDrawSurface4 *rt;
3455 IDirect3D3 *d3d;
3456 D3DCOLOR color;
3457 HWND window;
3458 HRESULT hr;
3459 D3DMATERIALHANDLE mat_handle;
3460 D3DMATERIAL mat_desc;
3461 DWORD rs;
3462 unsigned int i;
3463 ULONG ref;
3464 static D3DVERTEX quad[] =
3466 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3467 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3468 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3469 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3472 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
3473 static struct
3475 struct vec3 position;
3476 struct vec3 normal;
3477 DWORD diffuse, specular;
3479 quad2[] =
3481 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
3482 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
3483 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
3484 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
3487 static D3DLVERTEX lquad[] =
3489 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3490 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3491 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3492 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3495 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
3496 static struct
3498 struct vec3 position;
3499 DWORD diffuse, specular;
3500 struct vec2 texcoord;
3502 lquad2[] =
3504 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
3505 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
3506 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
3507 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
3510 static D3DTLVERTEX tlquad[] =
3512 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3513 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3514 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3515 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3518 static const struct
3520 DWORD vertextype;
3521 void *data;
3522 DWORD d3drs_lighting, d3drs_specular;
3523 DWORD draw_flags;
3524 D3DCOLOR color;
3526 tests[] =
3528 /* Lighting is enabled when all of these conditions are met:
3529 * 1) No pretransformed position(D3DFVF_XYZRHW)
3530 * 2) Normals are available (D3DFVF_NORMAL)
3531 * 3) D3DDP_DONOTLIGHT is not set.
3533 * D3DRENDERSTATE_LIGHTING is ignored, it is not defined
3534 * in this d3d version */
3536 /* 0 */
3537 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x0000ff00},
3538 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
3539 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
3540 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
3541 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x0000ff00},
3542 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
3543 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
3544 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
3546 /* 8 */
3547 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x0000ff00},
3548 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
3549 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
3550 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
3551 /* The specular color in the vertex is ignored because
3552 * D3DRENDERSTATE_COLORVERTEX is not enabled */
3553 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x0000ff00},
3554 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
3555 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
3556 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
3558 /* 16 */
3559 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
3560 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x00ff0000},
3561 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
3562 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
3563 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
3564 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x00ff8080},
3565 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
3566 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
3568 /* 24 */
3569 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
3570 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x00ff0000},
3571 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
3572 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
3573 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
3574 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x00ff8080},
3575 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
3576 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
3578 /* 32 */
3579 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
3580 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
3581 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
3582 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
3583 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
3584 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
3585 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
3586 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
3589 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3590 0, 0, 640, 480, 0, 0, 0, 0);
3592 if (!(device = create_device(window, DDSCL_NORMAL)))
3594 skip("Failed to create a 3D device, skipping test.\n");
3595 DestroyWindow(window);
3596 return;
3598 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
3599 ok(SUCCEEDED(hr), "Failed to get IDirect3D3 interface, hr %#x.\n", hr);
3601 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
3602 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3604 viewport = create_viewport(device, 0, 0, 640, 480);
3605 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
3606 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
3608 memset(&mat_desc, 0, sizeof(mat_desc));
3609 mat_desc.dwSize = sizeof(mat_desc);
3610 U2(U3(mat_desc).dcvEmissive).g = 1.0f;
3611 hr = IDirect3D3_CreateMaterial(d3d, &emissive, NULL);
3612 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
3613 hr = IDirect3DMaterial3_SetMaterial(emissive, &mat_desc);
3614 ok(SUCCEEDED(hr), "Failed to set material, hr %#x.\n", hr);
3615 hr = IDirect3DMaterial3_GetHandle(emissive, device, &mat_handle);
3616 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
3617 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
3618 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
3619 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
3620 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
3622 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
3623 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
3624 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected FALSE.\n", rs);
3626 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
3628 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
3629 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3631 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
3632 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
3633 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
3634 tests[i].d3drs_specular);
3635 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
3637 hr = IDirect3DDevice3_BeginScene(device);
3638 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3639 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
3640 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
3641 hr = IDirect3DDevice3_EndScene(device);
3642 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3644 color = get_surface_color(rt, 320, 240);
3645 ok(compare_color(color, tests[i].color, 1),
3646 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
3647 color, tests[i].color, i);
3650 IDirect3DMaterial3_Release(emissive);
3651 IDirectDrawSurface4_Release(rt);
3652 ref = IDirect3DDevice3_Release(device);
3653 ok(ref == 0, "Device not properly released, refcount %u.\n", ref);
3654 ref = IDirect3D3_Release(d3d);
3655 ok(ref == 0, "D3d not properly released, refcount %u.\n", ref);
3656 DestroyWindow(window);
3659 static struct
3661 BOOL received;
3662 IDirectDraw4 *ddraw;
3663 HWND window;
3664 DWORD coop_level;
3665 } activateapp_testdata;
3667 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3669 if (message == WM_ACTIVATEAPP)
3671 if (activateapp_testdata.ddraw)
3673 HRESULT hr;
3674 activateapp_testdata.received = FALSE;
3675 hr = IDirectDraw4_SetCooperativeLevel(activateapp_testdata.ddraw,
3676 activateapp_testdata.window, activateapp_testdata.coop_level);
3677 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
3678 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
3680 activateapp_testdata.received = TRUE;
3683 return DefWindowProcA(hwnd, message, wparam, lparam);
3686 static void test_coop_level_activateapp(void)
3688 IDirectDraw4 *ddraw;
3689 HRESULT hr;
3690 HWND window;
3691 WNDCLASSA wc = {0};
3692 DDSURFACEDESC2 ddsd;
3693 IDirectDrawSurface4 *surface;
3695 if (!(ddraw = create_ddraw()))
3697 skip("Failed to create a ddraw object, skipping test.\n");
3698 return;
3701 wc.lpfnWndProc = activateapp_test_proc;
3702 wc.lpszClassName = "ddraw_test_wndproc_wc";
3703 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3705 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
3706 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
3708 /* Exclusive with window already active. */
3709 SetActiveWindow(window);
3710 activateapp_testdata.received = FALSE;
3711 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3712 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3713 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
3714 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3715 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3717 /* Exclusive with window not active. */
3718 SetActiveWindow(NULL);
3719 activateapp_testdata.received = FALSE;
3720 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3721 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3722 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3723 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3724 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3726 /* Normal with window not active, then exclusive with the same window. */
3727 SetActiveWindow(NULL);
3728 activateapp_testdata.received = FALSE;
3729 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3730 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3731 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
3732 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3733 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3734 /* Except in the first SetCooperativeLevel call, Windows XP randomly does not send
3735 * WM_ACTIVATEAPP. Windows 7 sends the message reliably. Mark the XP behavior broken. */
3736 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
3737 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3738 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3739 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3741 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
3742 SetActiveWindow(NULL);
3743 activateapp_testdata.received = FALSE;
3744 activateapp_testdata.ddraw = ddraw;
3745 activateapp_testdata.window = window;
3746 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
3747 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3748 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3749 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
3750 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3751 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3752 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3754 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
3755 * succeeding. Another switch to exclusive and back to normal is needed to release the
3756 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
3757 * WM_ACTIVATEAPP messages. */
3758 activateapp_testdata.ddraw = NULL;
3759 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3760 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3761 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3762 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3764 /* Setting DDSCL_NORMAL with recursive invocation. */
3765 SetActiveWindow(NULL);
3766 activateapp_testdata.received = FALSE;
3767 activateapp_testdata.ddraw = ddraw;
3768 activateapp_testdata.window = window;
3769 activateapp_testdata.coop_level = DDSCL_NORMAL;
3770 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3771 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3772 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
3773 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3775 /* DDraw is in exlusive mode now. */
3776 memset(&ddsd, 0, sizeof(ddsd));
3777 ddsd.dwSize = sizeof(ddsd);
3778 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
3779 ddsd.dwBackBufferCount = 1;
3780 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
3781 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
3782 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3783 IDirectDrawSurface4_Release(surface);
3785 /* Recover again, just to be sure. */
3786 activateapp_testdata.ddraw = NULL;
3787 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3788 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3789 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3790 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3792 DestroyWindow(window);
3793 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3794 IDirectDraw4_Release(ddraw);
3797 static void test_texturemanage(void)
3799 IDirectDraw4 *ddraw;
3800 HRESULT hr;
3801 DDSURFACEDESC2 ddsd;
3802 IDirectDrawSurface4 *surface;
3803 unsigned int i;
3804 DDCAPS hal_caps, hel_caps;
3805 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
3806 static const struct
3808 DWORD caps_in, caps2_in;
3809 HRESULT hr;
3810 DWORD caps_out, caps2_out;
3812 tests[] =
3814 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
3815 ~0U, ~0U},
3816 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
3817 ~0U, ~0U},
3818 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
3819 ~0U, ~0U},
3820 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
3821 ~0U, ~0U},
3822 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
3823 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
3824 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
3825 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
3826 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
3827 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
3828 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
3829 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
3831 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
3832 ~0U, ~0U},
3833 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
3834 ~0U, ~0U},
3835 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
3836 ~0U, ~0U},
3837 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
3838 ~0U, ~0U},
3839 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
3840 ~0U, ~0U},
3841 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
3842 ~0U, ~0U},
3843 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
3844 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
3845 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
3846 DDSCAPS_SYSTEMMEMORY, 0},
3849 if (!(ddraw = create_ddraw()))
3851 skip("Failed to create a ddraw object, skipping test.\n");
3852 return;
3855 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3856 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3858 memset(&hal_caps, 0, sizeof(hal_caps));
3859 hal_caps.dwSize = sizeof(hal_caps);
3860 memset(&hel_caps, 0, sizeof(hel_caps));
3861 hel_caps.dwSize = sizeof(hel_caps);
3862 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, &hel_caps);
3863 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
3864 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
3866 skip("Managed textures not supported, skipping managed texture test.\n");
3867 IDirectDraw4_Release(ddraw);
3868 return;
3871 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
3873 memset(&ddsd, 0, sizeof(ddsd));
3874 ddsd.dwSize = sizeof(ddsd);
3875 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
3876 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
3877 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
3878 ddsd.dwWidth = 4;
3879 ddsd.dwHeight = 4;
3881 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
3882 ok(hr == tests[i].hr, "Got unexpected, hr %#x, case %u.\n", hr, i);
3883 if (FAILED(hr))
3884 continue;
3886 memset(&ddsd, 0, sizeof(ddsd));
3887 ddsd.dwSize = sizeof(ddsd);
3888 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
3889 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3891 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
3892 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
3893 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
3894 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
3895 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
3896 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
3898 IDirectDrawSurface4_Release(surface);
3901 IDirectDraw4_Release(ddraw);
3904 #define SUPPORT_DXT1 0x01
3905 #define SUPPORT_DXT2 0x02
3906 #define SUPPORT_DXT3 0x04
3907 #define SUPPORT_DXT4 0x08
3908 #define SUPPORT_DXT5 0x10
3909 #define SUPPORT_YUY2 0x20
3910 #define SUPPORT_UYVY 0x40
3912 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
3914 DWORD *supported_fmts = ctx;
3916 if (!(fmt->dwFlags & DDPF_FOURCC))
3917 return DDENUMRET_OK;
3919 switch (fmt->dwFourCC)
3921 case MAKEFOURCC('D','X','T','1'):
3922 *supported_fmts |= SUPPORT_DXT1;
3923 break;
3924 case MAKEFOURCC('D','X','T','2'):
3925 *supported_fmts |= SUPPORT_DXT2;
3926 break;
3927 case MAKEFOURCC('D','X','T','3'):
3928 *supported_fmts |= SUPPORT_DXT3;
3929 break;
3930 case MAKEFOURCC('D','X','T','4'):
3931 *supported_fmts |= SUPPORT_DXT4;
3932 break;
3933 case MAKEFOURCC('D','X','T','5'):
3934 *supported_fmts |= SUPPORT_DXT5;
3935 break;
3936 case MAKEFOURCC('Y','U','Y','2'):
3937 *supported_fmts |= SUPPORT_YUY2;
3938 break;
3939 case MAKEFOURCC('U','Y','V','Y'):
3940 *supported_fmts |= SUPPORT_UYVY;
3941 break;
3942 default:
3943 break;
3946 return DDENUMRET_OK;
3949 static void test_block_formats_creation(void)
3951 HRESULT hr, expect_hr;
3952 unsigned int i, j, w, h;
3953 HWND window;
3954 IDirectDraw4 *ddraw;
3955 IDirect3D3 *d3d;
3956 IDirect3DDevice3 *device;
3957 IDirectDrawSurface4 *surface;
3958 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
3959 DWORD num_fourcc_codes = 0, *fourcc_codes;
3960 DDSURFACEDESC2 ddsd;
3961 static const struct
3963 DWORD fourcc;
3964 const char *name;
3965 DWORD support_flag;
3966 unsigned int block_width;
3967 unsigned int block_height;
3968 BOOL create_size_checked, overlay;
3970 formats[] =
3972 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, TRUE, FALSE},
3973 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, TRUE, FALSE},
3974 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, TRUE, FALSE},
3975 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, TRUE, FALSE},
3976 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, TRUE, FALSE},
3977 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, FALSE, TRUE },
3978 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, FALSE, TRUE },
3980 const struct
3982 DWORD caps, caps2;
3983 const char *name;
3984 BOOL overlay;
3986 types[] =
3988 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
3989 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
3991 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
3992 * Other hw / drivers successfully create those surfaces. Ignore them, this
3993 * suggests that no game uses this, otherwise Nvidia would support it. */
3995 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
3996 "videomemory texture", FALSE
3999 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
4000 "videomemory overlay", TRUE
4003 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
4004 "systemmemory texture", FALSE
4007 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
4008 "managed texture", FALSE
4012 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4013 0, 0, 640, 480, 0, 0, 0, 0);
4015 if (!(device = create_device(window, DDSCL_NORMAL)))
4017 skip("Failed to create a 3D device, skipping test.\n");
4018 DestroyWindow(window);
4019 return;
4022 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
4023 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
4024 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **) &ddraw);
4025 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
4026 IDirect3D3_Release(d3d);
4028 hr = IDirect3DDevice3_EnumTextureFormats(device, test_block_formats_creation_cb,
4029 &supported_fmts);
4030 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
4032 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
4033 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
4034 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
4035 num_fourcc_codes * sizeof(*fourcc_codes));
4036 if (!fourcc_codes)
4037 goto cleanup;
4038 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
4039 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
4040 for (i = 0; i < num_fourcc_codes; i++)
4042 for (j = 0; j < sizeof(formats) / sizeof(*formats); j++)
4044 if (fourcc_codes[i] == formats[j].fourcc)
4045 supported_overlay_fmts |= formats[j].support_flag;
4048 HeapFree(GetProcessHeap(), 0, fourcc_codes);
4050 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
4052 for (j = 0; j < sizeof(types) / sizeof(*types); j++)
4054 BOOL support;
4055 if (formats[i].overlay != types[j].overlay)
4056 continue;
4058 if (formats[i].overlay)
4059 support = supported_overlay_fmts & formats[i].support_flag;
4060 else
4061 support = supported_fmts & formats[i].support_flag;
4063 for (w = 1; w <= 8; w++)
4065 for (h = 1; h <= 8; h++)
4067 BOOL block_aligned = TRUE;
4068 BOOL todo = FALSE;
4070 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
4071 block_aligned = FALSE;
4073 memset(&ddsd, 0, sizeof(ddsd));
4074 ddsd.dwSize = sizeof(ddsd);
4075 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4076 ddsd.ddsCaps.dwCaps = types[j].caps;
4077 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
4078 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
4079 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
4080 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
4081 ddsd.dwWidth = w;
4082 ddsd.dwHeight = h;
4084 /* TODO: Handle power of two limitations. I cannot test the pow2
4085 * behavior on windows because I have no hardware that doesn't at
4086 * least support np2_conditional. There's probably no HW that
4087 * supports DXTN textures but no conditional np2 textures. */
4088 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
4089 expect_hr = DDERR_INVALIDPARAMS;
4090 else if (formats[i].create_size_checked && !block_aligned)
4092 expect_hr = DDERR_INVALIDPARAMS;
4093 if (!(types[j].caps & DDSCAPS_TEXTURE))
4094 todo = TRUE;
4096 else
4097 expect_hr = D3D_OK;
4099 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
4100 if (todo)
4101 todo_wine ok(hr == expect_hr,
4102 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
4103 hr, formats[i].name, types[j].name, w, h, expect_hr);
4104 else
4105 ok(hr == expect_hr,
4106 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
4107 hr, formats[i].name, types[j].name, w, h, expect_hr);
4109 if (SUCCEEDED(hr))
4110 IDirectDrawSurface4_Release(surface);
4116 cleanup:
4117 IDirectDraw4_Release(ddraw);
4118 IDirect3DDevice3_Release(device);
4119 DestroyWindow(window);
4122 struct format_support_check
4124 const DDPIXELFORMAT *format;
4125 BOOL supported;
4128 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
4130 struct format_support_check *format = ctx;
4132 if (!memcmp(format->format, fmt, sizeof(*fmt)))
4134 format->supported = TRUE;
4135 return DDENUMRET_CANCEL;
4138 return DDENUMRET_OK;
4141 static void test_unsupported_formats(void)
4143 HRESULT hr;
4144 BOOL expect_success;
4145 HWND window;
4146 IDirectDraw4 *ddraw;
4147 IDirect3D3 *d3d;
4148 IDirect3DDevice3 *device;
4149 IDirectDrawSurface4 *surface;
4150 DDSURFACEDESC2 ddsd;
4151 unsigned int i, j;
4152 DWORD expected_caps;
4153 static const struct
4155 const char *name;
4156 DDPIXELFORMAT fmt;
4158 formats[] =
4161 "D3DFMT_A8R8G8B8",
4163 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
4164 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
4168 "D3DFMT_P8",
4170 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
4171 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
4175 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
4177 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4178 0, 0, 640, 480, 0, 0, 0, 0);
4180 if (!(device = create_device(window, DDSCL_NORMAL)))
4182 skip("Failed to create a 3D device, skipping test.\n");
4183 DestroyWindow(window);
4184 return;
4187 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
4188 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
4189 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **) &ddraw);
4190 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
4191 IDirect3D3_Release(d3d);
4193 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
4195 struct format_support_check check = {&formats[i].fmt, FALSE};
4196 hr = IDirect3DDevice3_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
4197 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
4199 for (j = 0; j < sizeof(caps) / sizeof(*caps); j++)
4201 memset(&ddsd, 0, sizeof(ddsd));
4202 ddsd.dwSize = sizeof(ddsd);
4203 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4204 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
4205 ddsd.dwWidth = 4;
4206 ddsd.dwHeight = 4;
4207 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
4209 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
4210 expect_success = FALSE;
4211 else
4212 expect_success = TRUE;
4214 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
4215 ok(SUCCEEDED(hr) == expect_success,
4216 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
4217 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
4218 if (FAILED(hr))
4219 continue;
4221 memset(&ddsd, 0, sizeof(ddsd));
4222 ddsd.dwSize = sizeof(ddsd);
4223 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
4224 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4226 if (caps[j] & DDSCAPS_VIDEOMEMORY)
4227 expected_caps = DDSCAPS_VIDEOMEMORY;
4228 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
4229 expected_caps = DDSCAPS_SYSTEMMEMORY;
4230 else if (check.supported)
4231 expected_caps = DDSCAPS_VIDEOMEMORY;
4232 else
4233 expected_caps = DDSCAPS_SYSTEMMEMORY;
4235 ok(ddsd.ddsCaps.dwCaps & expected_caps,
4236 "Expected capability %#x, format %s, input cap %#x.\n",
4237 expected_caps, formats[i].name, caps[j]);
4239 IDirectDrawSurface4_Release(surface);
4243 IDirectDraw4_Release(ddraw);
4244 IDirect3DDevice3_Release(device);
4245 DestroyWindow(window);
4248 static void test_rt_caps(void)
4250 PALETTEENTRY palette_entries[256];
4251 IDirectDrawPalette *palette;
4252 IDirectDraw4 *ddraw;
4253 DDPIXELFORMAT z_fmt;
4254 IDirect3D3 *d3d;
4255 unsigned int i;
4256 ULONG refcount;
4257 HWND window;
4258 HRESULT hr;
4260 static const DDPIXELFORMAT p8_fmt =
4262 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
4263 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
4266 const struct
4268 const DDPIXELFORMAT *pf;
4269 DWORD caps_in;
4270 DWORD caps_out;
4271 HRESULT create_device_hr;
4272 HRESULT set_rt_hr, alternative_set_rt_hr;
4274 test_data[] =
4277 NULL,
4278 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
4279 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4280 D3D_OK,
4281 D3D_OK,
4282 D3D_OK,
4285 NULL,
4286 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4287 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4288 D3D_OK,
4289 D3D_OK,
4290 D3D_OK,
4293 NULL,
4294 DDSCAPS_OFFSCREENPLAIN,
4295 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4296 DDERR_INVALIDCAPS,
4297 DDERR_INVALIDCAPS,
4298 DDERR_INVALIDCAPS,
4301 NULL,
4302 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4303 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4304 D3DERR_SURFACENOTINVIDMEM,
4305 D3D_OK,
4306 D3D_OK,
4309 NULL,
4310 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4311 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4312 DDERR_INVALIDCAPS,
4313 DDERR_INVALIDCAPS,
4314 DDERR_INVALIDCAPS,
4317 NULL,
4318 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
4319 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4320 D3D_OK,
4321 D3D_OK,
4322 D3D_OK,
4325 NULL,
4326 DDSCAPS_3DDEVICE,
4327 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4328 D3D_OK,
4329 D3D_OK,
4330 D3D_OK,
4333 NULL,
4335 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4336 DDERR_INVALIDCAPS,
4337 DDERR_INVALIDCAPS,
4338 DDERR_INVALIDCAPS,
4341 NULL,
4342 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4343 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4344 D3DERR_SURFACENOTINVIDMEM,
4345 D3D_OK,
4346 D3D_OK,
4349 NULL,
4350 DDSCAPS_SYSTEMMEMORY,
4351 DDSCAPS_SYSTEMMEMORY,
4352 DDERR_INVALIDCAPS,
4353 DDERR_INVALIDCAPS,
4354 DDERR_INVALIDCAPS,
4357 &p8_fmt,
4359 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4360 DDERR_INVALIDCAPS,
4361 DDERR_INVALIDCAPS,
4362 DDERR_INVALIDCAPS,
4365 &p8_fmt,
4366 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4367 ~0U /* AMD r200 */,
4368 DDERR_NOPALETTEATTACHED,
4369 DDERR_INVALIDCAPS,
4370 DDERR_INVALIDCAPS,
4373 &p8_fmt,
4374 DDSCAPS_OFFSCREENPLAIN,
4375 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
4376 DDERR_INVALIDCAPS,
4377 DDERR_INVALIDCAPS,
4378 DDERR_INVALIDCAPS,
4381 &p8_fmt,
4382 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4383 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4384 DDERR_NOPALETTEATTACHED,
4385 DDERR_INVALIDCAPS,
4386 DDERR_INVALIDCAPS,
4389 &p8_fmt,
4390 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4391 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4392 DDERR_INVALIDCAPS,
4393 DDERR_INVALIDCAPS,
4394 DDERR_INVALIDCAPS,
4397 &z_fmt,
4398 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
4399 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
4400 DDERR_INVALIDCAPS,
4401 DDERR_INVALIDPIXELFORMAT,
4402 D3D_OK /* r200 */,
4405 &z_fmt,
4406 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4407 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
4408 DDERR_INVALIDCAPS,
4409 DDERR_INVALIDPIXELFORMAT,
4410 D3D_OK /* r200 */,
4413 &z_fmt,
4414 DDSCAPS_ZBUFFER,
4415 DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
4416 DDERR_INVALIDCAPS,
4417 DDERR_INVALIDCAPS,
4418 DDERR_INVALIDCAPS,
4421 &z_fmt,
4422 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4423 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4424 DDERR_INVALIDCAPS,
4425 DDERR_INVALIDPIXELFORMAT,
4426 D3D_OK /* r200 */,
4429 &z_fmt,
4430 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
4431 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
4432 DDERR_INVALIDCAPS,
4433 DDERR_INVALIDCAPS,
4434 DDERR_INVALIDCAPS,
4438 if (!(ddraw = create_ddraw()))
4440 skip("Failed to create a ddraw object, skipping test.\n");
4441 return;
4444 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4445 0, 0, 640, 480, 0, 0, 0, 0);
4446 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4447 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4449 if (FAILED(hr = IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
4451 skip("D3D interface is not available, skipping test.\n");
4452 goto done;
4455 memset(&z_fmt, 0, sizeof(z_fmt));
4456 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
4457 if (FAILED(hr) || !z_fmt.dwSize)
4459 skip("No depth buffer formats available, skipping test.\n");
4460 IDirect3D3_Release(d3d);
4461 goto done;
4464 memset(palette_entries, 0, sizeof(palette_entries));
4465 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
4466 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
4468 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
4470 IDirectDrawSurface4 *surface, *rt, *expected_rt, *tmp;
4471 DDSURFACEDESC2 surface_desc;
4472 IDirect3DDevice3 *device;
4474 memset(&surface_desc, 0, sizeof(surface_desc));
4475 surface_desc.dwSize = sizeof(surface_desc);
4476 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4477 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
4478 if (test_data[i].pf)
4480 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
4481 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
4483 surface_desc.dwWidth = 640;
4484 surface_desc.dwHeight = 480;
4485 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4486 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
4487 i, test_data[i].caps_in, hr);
4489 memset(&surface_desc, 0, sizeof(surface_desc));
4490 surface_desc.dwSize = sizeof(surface_desc);
4491 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
4492 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
4493 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
4494 "Test %u: Got unexpected caps %#x, expected %#x.\n",
4495 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
4497 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
4498 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
4499 i, hr, test_data[i].create_device_hr);
4500 if (FAILED(hr))
4502 if (hr == DDERR_NOPALETTEATTACHED)
4504 hr = IDirectDrawSurface4_SetPalette(surface, palette);
4505 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
4506 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
4507 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
4508 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
4509 else
4510 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
4512 IDirectDrawSurface4_Release(surface);
4514 memset(&surface_desc, 0, sizeof(surface_desc));
4515 surface_desc.dwSize = sizeof(surface_desc);
4516 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4517 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4518 surface_desc.dwWidth = 640;
4519 surface_desc.dwHeight = 480;
4520 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4521 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
4523 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device, NULL);
4524 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
4527 memset(&surface_desc, 0, sizeof(surface_desc));
4528 surface_desc.dwSize = sizeof(surface_desc);
4529 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4530 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
4531 if (test_data[i].pf)
4533 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
4534 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
4536 surface_desc.dwWidth = 640;
4537 surface_desc.dwHeight = 480;
4538 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &rt, NULL);
4539 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
4540 i, test_data[i].caps_in, hr);
4542 hr = IDirect3DDevice3_SetRenderTarget(device, rt, 0);
4543 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
4544 "Test %u: Got unexpected hr %#x, expected %#x.\n",
4545 i, hr, test_data[i].set_rt_hr);
4546 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
4547 expected_rt = rt;
4548 else
4549 expected_rt = surface;
4551 hr = IDirect3DDevice3_GetRenderTarget(device, &tmp);
4552 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
4553 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
4555 IDirectDrawSurface4_Release(tmp);
4556 IDirectDrawSurface4_Release(rt);
4557 refcount = IDirect3DDevice3_Release(device);
4558 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
4559 refcount = IDirectDrawSurface4_Release(surface);
4560 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
4563 IDirectDrawPalette_Release(palette);
4564 IDirect3D3_Release(d3d);
4566 done:
4567 refcount = IDirectDraw4_Release(ddraw);
4568 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4569 DestroyWindow(window);
4572 static void test_primary_caps(void)
4574 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
4575 IDirectDrawSurface4 *surface;
4576 DDSURFACEDESC2 surface_desc;
4577 IDirectDraw4 *ddraw;
4578 unsigned int i;
4579 ULONG refcount;
4580 HWND window;
4581 HRESULT hr;
4583 static const struct
4585 DWORD coop_level;
4586 DWORD caps_in;
4587 DWORD back_buffer_count;
4588 HRESULT hr;
4589 DWORD caps_out;
4591 test_data[] =
4594 DDSCL_NORMAL,
4595 DDSCAPS_PRIMARYSURFACE,
4596 ~0u,
4597 DD_OK,
4598 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
4601 DDSCL_NORMAL,
4602 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
4603 ~0u,
4604 DDERR_INVALIDCAPS,
4605 ~0u,
4608 DDSCL_NORMAL,
4609 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
4610 ~0u,
4611 DDERR_INVALIDCAPS,
4612 ~0u,
4615 DDSCL_NORMAL,
4616 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
4617 ~0u,
4618 DDERR_INVALIDCAPS,
4619 ~0u,
4622 DDSCL_NORMAL,
4623 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
4624 ~0u,
4625 DDERR_INVALIDCAPS,
4626 ~0u,
4629 DDSCL_NORMAL,
4630 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
4631 ~0u,
4632 DDERR_INVALIDCAPS,
4633 ~0u,
4636 DDSCL_NORMAL,
4637 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4638 ~0u,
4639 DDERR_INVALIDCAPS,
4640 ~0u,
4643 DDSCL_NORMAL,
4644 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4646 DDERR_INVALIDCAPS,
4647 ~0u,
4650 DDSCL_NORMAL,
4651 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4653 DDERR_NOEXCLUSIVEMODE,
4654 ~0u,
4657 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4658 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4660 DDERR_INVALIDCAPS,
4661 ~0u,
4664 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4665 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4667 DD_OK,
4668 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
4671 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4672 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
4674 DDERR_INVALIDCAPS,
4675 ~0u,
4678 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4679 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
4681 DDERR_INVALIDCAPS,
4682 ~0u,
4686 if (!(ddraw = create_ddraw()))
4688 skip("Failed to create a ddraw object, skipping test.\n");
4689 return;
4692 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4693 0, 0, 640, 480, 0, 0, 0, 0);
4695 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
4697 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
4698 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4700 memset(&surface_desc, 0, sizeof(surface_desc));
4701 surface_desc.dwSize = sizeof(surface_desc);
4702 surface_desc.dwFlags = DDSD_CAPS;
4703 if (test_data[i].back_buffer_count != ~0u)
4704 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
4705 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
4706 surface_desc.dwBackBufferCount = test_data[i].back_buffer_count;
4707 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4708 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
4709 if (FAILED(hr))
4710 continue;
4712 memset(&surface_desc, 0, sizeof(surface_desc));
4713 surface_desc.dwSize = sizeof(surface_desc);
4714 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
4715 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
4716 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
4717 "Test %u: Got unexpected caps %#x, expected %#x.\n",
4718 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
4720 IDirectDrawSurface4_Release(surface);
4723 refcount = IDirectDraw4_Release(ddraw);
4724 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4725 DestroyWindow(window);
4728 static void test_surface_lock(void)
4730 IDirectDraw4 *ddraw;
4731 IDirect3D3 *d3d = NULL;
4732 IDirectDrawSurface4 *surface;
4733 HRESULT hr;
4734 HWND window;
4735 unsigned int i;
4736 DDSURFACEDESC2 ddsd;
4737 ULONG refcount;
4738 DDPIXELFORMAT z_fmt;
4739 static const struct
4741 DWORD caps;
4742 DWORD caps2;
4743 const char *name;
4745 tests[] =
4748 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
4750 "videomemory offscreenplain"
4753 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4755 "systemmemory offscreenplain"
4758 DDSCAPS_PRIMARYSURFACE,
4760 "primary"
4763 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
4765 "videomemory texture"
4768 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
4769 DDSCAPS2_OPAQUE,
4770 "opaque videomemory texture"
4773 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
4775 "systemmemory texture"
4778 DDSCAPS_TEXTURE,
4779 DDSCAPS2_TEXTUREMANAGE,
4780 "managed texture"
4783 DDSCAPS_TEXTURE,
4784 DDSCAPS2_D3DTEXTUREMANAGE,
4785 "managed texture"
4788 DDSCAPS_TEXTURE,
4789 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
4790 "opaque managed texture"
4793 DDSCAPS_TEXTURE,
4794 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
4795 "opaque managed texture"
4798 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4800 "render target"
4803 DDSCAPS_ZBUFFER,
4805 "Z buffer"
4809 if (!(ddraw = create_ddraw()))
4811 skip("Failed to create a ddraw object, skipping test.\n");
4812 return;
4815 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4816 0, 0, 640, 480, 0, 0, 0, 0);
4817 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4818 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4820 if (FAILED(hr = IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
4822 skip("D3D interface is not available, skipping test.\n");
4823 goto done;
4826 memset(&z_fmt, 0, sizeof(z_fmt));
4827 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
4828 if (FAILED(hr) || !z_fmt.dwSize)
4830 skip("No depth buffer formats available, skipping test.\n");
4831 goto done;
4834 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4836 memset(&ddsd, 0, sizeof(ddsd)),
4837 ddsd.dwSize = sizeof(ddsd);
4838 ddsd.dwFlags = DDSD_CAPS;
4839 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
4841 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
4842 ddsd.dwWidth = 64;
4843 ddsd.dwHeight = 64;
4845 if (tests[i].caps & DDSCAPS_ZBUFFER)
4847 ddsd.dwFlags |= DDSD_PIXELFORMAT;
4848 U4(ddsd).ddpfPixelFormat = z_fmt;
4850 ddsd.ddsCaps.dwCaps = tests[i].caps;
4851 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
4853 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
4854 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
4856 memset(&ddsd, 0, sizeof(ddsd)),
4857 ddsd.dwSize = sizeof(ddsd);
4858 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
4859 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
4860 if (SUCCEEDED(hr))
4862 hr = IDirectDrawSurface4_Unlock(surface, NULL);
4863 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
4866 IDirectDrawSurface4_Release(surface);
4869 done:
4870 if (d3d)
4871 IDirect3D3_Release(d3d);
4872 refcount = IDirectDraw4_Release(ddraw);
4873 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4874 DestroyWindow(window);
4877 static void test_surface_discard(void)
4879 IDirect3DDevice3 *device;
4880 IDirect3D3 *d3d;
4881 IDirectDraw4 *ddraw;
4882 HRESULT hr;
4883 HWND window;
4884 DDSURFACEDESC2 ddsd;
4885 IDirectDrawSurface4 *surface, *target;
4886 void *addr;
4887 static const struct
4889 DWORD caps, caps2;
4890 BOOL discard;
4892 tests[] =
4894 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
4895 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
4896 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
4897 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
4898 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
4899 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
4900 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
4901 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
4903 unsigned int i;
4905 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4906 0, 0, 640, 480, 0, 0, 0, 0);
4908 if (!(device = create_device(window, DDSCL_NORMAL)))
4910 skip("Failed to create a 3D device, skipping test.\n");
4911 DestroyWindow(window);
4912 return;
4914 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
4915 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
4916 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
4917 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
4918 hr = IDirect3DDevice3_GetRenderTarget(device, &target);
4919 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4921 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4923 BOOL discarded;
4925 memset(&ddsd, 0, sizeof(ddsd));
4926 ddsd.dwSize = sizeof(ddsd);
4927 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4928 ddsd.ddsCaps.dwCaps = tests[i].caps;
4929 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
4930 ddsd.dwWidth = 64;
4931 ddsd.dwHeight = 64;
4932 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
4933 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i);
4935 memset(&ddsd, 0, sizeof(ddsd));
4936 ddsd.dwSize = sizeof(ddsd);
4937 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, 0, NULL);
4938 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4939 addr = ddsd.lpSurface;
4940 hr = IDirectDrawSurface4_Unlock(surface, NULL);
4941 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4943 memset(&ddsd, 0, sizeof(ddsd));
4944 ddsd.dwSize = sizeof(ddsd);
4945 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
4946 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4947 discarded = ddsd.lpSurface != addr;
4948 hr = IDirectDrawSurface4_Unlock(surface, NULL);
4949 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4951 hr = IDirectDrawSurface4_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
4952 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
4954 memset(&ddsd, 0, sizeof(ddsd));
4955 ddsd.dwSize = sizeof(ddsd);
4956 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
4957 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4958 discarded |= ddsd.lpSurface != addr;
4959 hr = IDirectDrawSurface4_Unlock(surface, NULL);
4960 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4962 IDirectDrawSurface4_Release(surface);
4964 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
4965 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
4966 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
4969 IDirectDrawSurface4_Release(target);
4970 IDirectDraw4_Release(ddraw);
4971 IDirect3D3_Release(d3d);
4972 IDirect3DDevice3_Release(device);
4973 DestroyWindow(window);
4976 static void test_flip(void)
4978 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
4979 IDirectDrawSurface4 *primary, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
4980 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, 0};
4981 DDSURFACEDESC2 surface_desc;
4982 BOOL sysmem_primary;
4983 IDirectDraw4 *ddraw;
4984 D3DCOLOR color;
4985 ULONG refcount;
4986 HWND window;
4987 DDBLTFX fx;
4988 HRESULT hr;
4990 if (!(ddraw = create_ddraw()))
4992 skip("Failed to create a ddraw object, skipping test.\n");
4993 return;
4996 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4997 0, 0, 640, 480, 0, 0, 0, 0);
4999 hr = IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
5000 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
5001 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5002 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5004 memset(&surface_desc, 0, sizeof(surface_desc));
5005 surface_desc.dwSize = sizeof(surface_desc);
5006 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
5007 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
5008 surface_desc.dwBackBufferCount = 3;
5009 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
5010 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5012 memset(&surface_desc, 0, sizeof(surface_desc));
5013 surface_desc.dwSize = sizeof(surface_desc);
5014 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &surface_desc);
5015 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5016 ok((surface_desc.ddsCaps.dwCaps & ~placement)
5017 == (DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX),
5018 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
5019 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
5021 hr = IDirectDrawSurface4_GetAttachedSurface(primary, &caps, &backbuffer1);
5022 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5023 memset(&surface_desc, 0, sizeof(surface_desc));
5024 surface_desc.dwSize = sizeof(surface_desc);
5025 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer1, &surface_desc);
5026 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5027 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_BACKBUFFER),
5028 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
5030 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
5031 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5032 memset(&surface_desc, 0, sizeof(surface_desc));
5033 surface_desc.dwSize = sizeof(surface_desc);
5034 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer2, &surface_desc);
5035 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5036 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
5037 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
5039 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
5040 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5041 memset(&surface_desc, 0, sizeof(surface_desc));
5042 surface_desc.dwSize = sizeof(surface_desc);
5043 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer3, &surface_desc);
5044 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5045 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
5046 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
5048 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer3, &caps, &surface);
5049 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5050 ok(surface == primary, "Got unexpected surface %p, expected %p.\n", surface, primary);
5051 IDirectDrawSurface4_Release(surface);
5053 memset(&surface_desc, 0, sizeof(surface_desc));
5054 surface_desc.dwSize = sizeof(surface_desc);
5055 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5056 surface_desc.ddsCaps.dwCaps = 0;
5057 surface_desc.dwWidth = 640;
5058 surface_desc.dwHeight = 480;
5059 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5060 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5061 hr = IDirectDrawSurface4_Flip(primary, surface, DDFLIP_WAIT);
5062 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
5063 IDirectDrawSurface4_Release(surface);
5065 hr = IDirectDrawSurface4_Flip(primary, primary, DDFLIP_WAIT);
5066 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
5067 hr = IDirectDrawSurface4_Flip(backbuffer1, NULL, DDFLIP_WAIT);
5068 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
5069 hr = IDirectDrawSurface4_Flip(backbuffer2, NULL, DDFLIP_WAIT);
5070 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
5071 hr = IDirectDrawSurface4_Flip(backbuffer3, NULL, DDFLIP_WAIT);
5072 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
5074 memset(&fx, 0, sizeof(fx));
5075 fx.dwSize = sizeof(fx);
5076 U5(fx).dwFillColor = 0xffff0000;
5077 hr = IDirectDrawSurface4_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5078 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5079 U5(fx).dwFillColor = 0xff00ff00;
5080 hr = IDirectDrawSurface4_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5081 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5082 U5(fx).dwFillColor = 0xff0000ff;
5083 hr = IDirectDrawSurface4_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5084 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5086 hr = IDirectDrawSurface4_Flip(primary, NULL, DDFLIP_WAIT);
5087 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
5088 color = get_surface_color(backbuffer1, 320, 240);
5089 /* The testbot seems to just copy the contents of one surface to all the
5090 * others, instead of properly flipping. */
5091 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
5092 "Got unexpected color 0x%08x.\n", color);
5093 color = get_surface_color(backbuffer2, 320, 240);
5094 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
5095 U5(fx).dwFillColor = 0xffff0000;
5096 hr = IDirectDrawSurface4_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5097 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5099 hr = IDirectDrawSurface4_Flip(primary, NULL, DDFLIP_WAIT);
5100 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
5101 color = get_surface_color(backbuffer1, 320, 240);
5102 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
5103 "Got unexpected color 0x%08x.\n", color);
5104 color = get_surface_color(backbuffer2, 320, 240);
5105 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
5106 U5(fx).dwFillColor = 0xff00ff00;
5107 hr = IDirectDrawSurface4_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5108 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5110 hr = IDirectDrawSurface4_Flip(primary, NULL, DDFLIP_WAIT);
5111 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
5112 color = get_surface_color(backbuffer1, 320, 240);
5113 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
5114 "Got unexpected color 0x%08x.\n", color);
5115 color = get_surface_color(backbuffer2, 320, 240);
5116 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
5117 U5(fx).dwFillColor = 0xff0000ff;
5118 hr = IDirectDrawSurface4_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5119 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5121 hr = IDirectDrawSurface4_Flip(primary, backbuffer1, DDFLIP_WAIT);
5122 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
5123 color = get_surface_color(backbuffer2, 320, 240);
5124 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
5125 "Got unexpected color 0x%08x.\n", color);
5126 color = get_surface_color(backbuffer3, 320, 240);
5127 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
5128 U5(fx).dwFillColor = 0xffff0000;
5129 hr = IDirectDrawSurface4_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5130 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5132 hr = IDirectDrawSurface4_Flip(primary, backbuffer2, DDFLIP_WAIT);
5133 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
5134 color = get_surface_color(backbuffer1, 320, 240);
5135 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
5136 color = get_surface_color(backbuffer3, 320, 240);
5137 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
5138 "Got unexpected color 0x%08x.\n", color);
5139 U5(fx).dwFillColor = 0xff00ff00;
5140 hr = IDirectDrawSurface4_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5141 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5143 hr = IDirectDrawSurface4_Flip(primary, backbuffer3, DDFLIP_WAIT);
5144 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
5145 color = get_surface_color(backbuffer1, 320, 240);
5146 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
5147 "Got unexpected color 0x%08x.\n", color);
5148 color = get_surface_color(backbuffer2, 320, 240);
5149 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
5151 IDirectDrawSurface4_Release(backbuffer3);
5152 IDirectDrawSurface4_Release(backbuffer2);
5153 IDirectDrawSurface4_Release(backbuffer1);
5154 IDirectDrawSurface4_Release(primary);
5155 refcount = IDirectDraw4_Release(ddraw);
5156 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5157 DestroyWindow(window);
5160 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
5162 memset(ddsd, 0, sizeof(*ddsd));
5163 ddsd->dwSize = sizeof(*ddsd);
5166 static void test_set_surface_desc(void)
5168 IDirectDraw4 *ddraw;
5169 HWND window;
5170 HRESULT hr;
5171 DDSURFACEDESC2 ddsd;
5172 IDirectDrawSurface4 *surface;
5173 BYTE data[16*16*4];
5174 ULONG ref;
5175 unsigned int i;
5176 static const struct
5178 DWORD caps, caps2;
5179 BOOL supported;
5180 const char *name;
5182 invalid_caps_tests[] =
5184 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
5185 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
5186 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
5187 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
5188 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
5191 if (!(ddraw = create_ddraw()))
5193 skip("Failed to create a ddraw object, skipping test.\n");
5194 return;
5197 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5198 0, 0, 640, 480, 0, 0, 0, 0);
5200 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5201 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5203 reset_ddsd(&ddsd);
5204 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
5205 ddsd.dwWidth = 8;
5206 ddsd.dwHeight = 8;
5207 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5208 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
5209 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
5210 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5211 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5212 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
5213 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
5215 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5216 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5218 reset_ddsd(&ddsd);
5219 ddsd.dwFlags = DDSD_LPSURFACE;
5220 ddsd.lpSurface = data;
5221 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5222 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5224 /* Redundantly setting the same lpSurface is not an error. */
5225 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5226 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5227 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5228 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5229 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
5230 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
5232 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, 0, NULL);
5233 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5234 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
5235 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
5236 hr = IDirectDrawSurface4_Unlock(surface, NULL);
5237 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5239 reset_ddsd(&ddsd);
5240 ddsd.dwFlags = DDSD_LPSURFACE;
5241 ddsd.lpSurface = data;
5242 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 1);
5243 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
5245 ddsd.lpSurface = NULL;
5246 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5247 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
5249 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, NULL, 0);
5250 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
5252 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5253 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5254 ok(ddsd.ddsCaps.dwCaps == DDSCAPS_SYSTEMMEMORY, "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
5255 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
5257 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
5258 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5259 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
5261 ddsd.dwFlags = DDSD_CAPS;
5262 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5263 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
5265 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
5266 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
5267 ddsd.lpSurface = data;
5268 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5269 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
5270 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
5271 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5272 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
5273 ddsd.ddsCaps.dwCaps = 0;
5274 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
5275 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5276 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5278 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5279 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5280 ok(ddsd.ddsCaps.dwCaps == DDSCAPS_SYSTEMMEMORY, "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
5281 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
5283 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
5284 reset_ddsd(&ddsd);
5285 ddsd.dwFlags = DDSD_HEIGHT;
5286 ddsd.dwHeight = 16;
5287 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5288 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
5290 ddsd.lpSurface = data;
5291 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
5292 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5293 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5295 ddsd.dwHeight = 0;
5296 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5297 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
5299 reset_ddsd(&ddsd);
5300 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5301 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
5302 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
5303 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
5305 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0 */
5306 reset_ddsd(&ddsd);
5307 ddsd.dwFlags = DDSD_PITCH;
5308 U1(ddsd).lPitch = 8 * 4;
5309 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5310 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
5312 ddsd.dwFlags = DDSD_WIDTH;
5313 ddsd.dwWidth = 16;
5314 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5315 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
5317 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
5318 ddsd.lpSurface = data;
5319 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5320 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
5322 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
5323 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5324 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
5326 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5327 U1(ddsd).lPitch = 16 * 4;
5328 ddsd.dwWidth = 16;
5329 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5330 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5332 reset_ddsd(&ddsd);
5333 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
5334 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5335 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
5336 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
5337 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
5339 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
5341 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
5342 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5343 U1(ddsd).lPitch = 4 * 4;
5344 ddsd.lpSurface = data;
5345 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5346 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
5348 U1(ddsd).lPitch = 4;
5349 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5350 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
5352 U1(ddsd).lPitch = 16 * 4 + 1;
5353 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5354 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
5356 U1(ddsd).lPitch = 16 * 4 + 3;
5357 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5358 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
5360 U1(ddsd).lPitch = -4;
5361 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5362 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
5364 U1(ddsd).lPitch = 16 * 4;
5365 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5366 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5368 reset_ddsd(&ddsd);
5369 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5370 U1(ddsd).lPitch = 0;
5371 ddsd.dwWidth = 16;
5372 ddsd.lpSurface = data;
5373 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5374 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
5376 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5377 U1(ddsd).lPitch = 16 * 4;
5378 ddsd.dwWidth = 0;
5379 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5380 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
5382 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
5383 ddsd.dwFlags = DDSD_PIXELFORMAT;
5384 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5385 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
5386 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
5387 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5388 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5389 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
5390 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5391 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
5393 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
5394 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5395 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5397 /* Can't set color keys. */
5398 reset_ddsd(&ddsd);
5399 ddsd.dwFlags = DDSD_CKSRCBLT;
5400 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
5401 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
5402 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5403 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
5405 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
5406 ddsd.lpSurface = data;
5407 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5408 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
5410 IDirectDrawSurface4_Release(surface);
5412 /* SetSurfaceDesc needs systemmemory surfaces.
5414 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
5415 for (i = 0; i < sizeof(invalid_caps_tests) / sizeof(*invalid_caps_tests); i++)
5417 reset_ddsd(&ddsd);
5418 ddsd.dwFlags = DDSD_CAPS;
5419 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
5420 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
5421 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
5423 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5424 ddsd.dwWidth = 8;
5425 ddsd.dwHeight = 8;
5426 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5427 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
5428 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
5429 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5430 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5431 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
5434 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5435 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW, "Failed to create surface, hr %#x.\n", hr);
5436 if (FAILED(hr))
5438 skip("Cannot create a %s surface, skipping vidmem SetSurfaceDesc test.\n",
5439 invalid_caps_tests[i].name);
5440 goto done;
5443 reset_ddsd(&ddsd);
5444 ddsd.dwFlags = DDSD_LPSURFACE;
5445 ddsd.lpSurface = data;
5446 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5447 if (invalid_caps_tests[i].supported)
5449 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5451 else
5453 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
5454 invalid_caps_tests[i].name, hr);
5456 /* Check priority of error conditions. */
5457 ddsd.dwFlags = DDSD_WIDTH;
5458 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5459 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
5460 invalid_caps_tests[i].name, hr);
5463 IDirectDrawSurface4_Release(surface);
5466 done:
5467 ref = IDirectDraw4_Release(ddraw);
5468 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5469 DestroyWindow(window);
5472 static void test_user_memory_getdc(void)
5474 IDirectDraw4 *ddraw;
5475 HWND window;
5476 HRESULT hr;
5477 DDSURFACEDESC2 ddsd;
5478 IDirectDrawSurface4 *surface;
5479 DWORD data[16][16];
5480 ULONG ref;
5481 HDC dc;
5483 if (!(ddraw = create_ddraw()))
5485 skip("Failed to create a ddraw object, skipping test.\n");
5486 return;
5489 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5490 0, 0, 640, 480, 0, 0, 0, 0);
5492 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5493 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5495 reset_ddsd(&ddsd);
5496 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
5497 ddsd.dwWidth = 16;
5498 ddsd.dwHeight = 16;
5499 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5500 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5501 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5502 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5503 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5504 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5505 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
5506 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
5507 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5509 memset(data, 0xaa, sizeof(data));
5510 reset_ddsd(&ddsd);
5511 ddsd.dwFlags = DDSD_LPSURFACE;
5512 ddsd.lpSurface = data;
5513 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
5514 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5516 hr = IDirectDrawSurface4_GetDC(surface, &dc);
5517 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
5518 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
5519 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
5520 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
5521 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
5523 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
5524 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
5526 IDirectDrawSurface4_Release(surface);
5527 ref = IDirectDraw4_Release(ddraw);
5528 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5529 DestroyWindow(window);
5532 START_TEST(ddraw4)
5534 test_process_vertices();
5535 test_coop_level_create_device_window();
5536 test_clipper_blt();
5537 test_coop_level_d3d_state();
5538 test_surface_interface_mismatch();
5539 test_coop_level_threaded();
5540 test_depth_blit();
5541 test_texture_load_ckey();
5542 test_viewport();
5543 test_zenable();
5544 test_ck_rgba();
5545 test_ck_default();
5546 test_surface_qi();
5547 test_device_qi();
5548 test_wndproc();
5549 test_window_style();
5550 test_redundant_mode_set();
5551 test_coop_level_mode_set();
5552 test_coop_level_mode_set_multi();
5553 test_initialize();
5554 test_coop_level_surf_create();
5555 test_vb_discard();
5556 test_coop_level_multi_window();
5557 test_draw_strided();
5558 test_clear_rect_count();
5559 test_coop_level_versions();
5560 test_lighting_interface_versions();
5561 test_coop_level_activateapp();
5562 test_texturemanage();
5563 test_block_formats_creation();
5564 test_unsupported_formats();
5565 test_rt_caps();
5566 test_primary_caps();
5567 test_surface_lock();
5568 test_surface_discard();
5569 test_flip();
5570 test_set_surface_desc();
5571 test_user_memory_getdc();