ddraw/tests: Nvidia has an off-by-one rectangle handling bug.
[wine/multimedia.git] / dlls / ddraw / tests / ddraw1.c
blobc5caff3f9f3a2aca7a31939b7b873ea56c97be5d
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 "d3d.h"
24 struct create_window_thread_param
26 HWND window;
27 HANDLE window_created;
28 HANDLE destroy_window;
29 HANDLE thread;
32 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
34 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
35 c1 >>= 8; c2 >>= 8;
36 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
37 c1 >>= 8; c2 >>= 8;
38 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
39 c1 >>= 8; c2 >>= 8;
40 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
41 return TRUE;
44 static DWORD WINAPI create_window_thread_proc(void *param)
46 struct create_window_thread_param *p = param;
47 DWORD res;
48 BOOL ret;
50 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
51 0, 0, 640, 480, 0, 0, 0, 0);
52 ret = SetEvent(p->window_created);
53 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
55 for (;;)
57 MSG msg;
59 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
60 DispatchMessageA(&msg);
61 res = WaitForSingleObject(p->destroy_window, 100);
62 if (res == WAIT_OBJECT_0)
63 break;
64 if (res != WAIT_TIMEOUT)
66 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
67 break;
71 DestroyWindow(p->window);
73 return 0;
76 static void create_window_thread(struct create_window_thread_param *p)
78 DWORD res, tid;
80 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
81 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
82 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
83 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
84 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
85 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
86 res = WaitForSingleObject(p->window_created, INFINITE);
87 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
90 static void destroy_window_thread(struct create_window_thread_param *p)
92 SetEvent(p->destroy_window);
93 WaitForSingleObject(p->thread, INFINITE);
94 CloseHandle(p->destroy_window);
95 CloseHandle(p->window_created);
96 CloseHandle(p->thread);
99 static HRESULT set_display_mode(IDirectDraw *ddraw, DWORD width, DWORD height)
101 if (SUCCEEDED(IDirectDraw_SetDisplayMode(ddraw, width, height, 32)))
102 return DD_OK;
103 return IDirectDraw_SetDisplayMode(ddraw, width, height, 24);
106 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
108 RECT rect = {x, y, x + 1, y + 1};
109 DDSURFACEDESC surface_desc;
110 D3DCOLOR color;
111 HRESULT hr;
113 memset(&surface_desc, 0, sizeof(surface_desc));
114 surface_desc.dwSize = sizeof(surface_desc);
116 hr = IDirectDrawSurface_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
117 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
118 if (FAILED(hr))
119 return 0xdeadbeef;
121 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
123 hr = IDirectDrawSurface_Unlock(surface, NULL);
124 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
126 return color;
129 static void emit_process_vertices(void **ptr, WORD base_idx, DWORD vertex_count)
131 D3DINSTRUCTION *inst = *ptr;
132 D3DPROCESSVERTICES *pv = (D3DPROCESSVERTICES *)(inst + 1);
134 inst->bOpcode = D3DOP_PROCESSVERTICES;
135 inst->bSize = sizeof(*pv);
136 inst->wCount = 1;
138 pv->dwFlags = D3DPROCESSVERTICES_COPY;
139 pv->wStart = base_idx;
140 pv->wDest = 0;
141 pv->dwCount = vertex_count;
142 pv->dwReserved = 0;
144 *ptr = pv + 1;
147 static void emit_set_rs(void **ptr, D3DRENDERSTATETYPE state, DWORD value)
149 D3DINSTRUCTION *inst = *ptr;
150 D3DSTATE *rs = (D3DSTATE *)(inst + 1);
152 inst->bOpcode = D3DOP_STATERENDER;
153 inst->bSize = sizeof(*rs);
154 inst->wCount = 1;
156 U1(*rs).drstRenderStateType = state;
157 U2(*rs).dwArg[0] = value;
159 *ptr = rs + 1;
162 static void emit_tquad(void **ptr, WORD base_idx)
164 D3DINSTRUCTION *inst = *ptr;
165 D3DTRIANGLE *tri = (D3DTRIANGLE *)(inst + 1);
167 inst->bOpcode = D3DOP_TRIANGLE;
168 inst->bSize = sizeof(*tri);
169 inst->wCount = 2;
171 U1(*tri).v1 = base_idx;
172 U2(*tri).v2 = base_idx + 1;
173 U3(*tri).v3 = base_idx + 2;
174 tri->wFlags = D3DTRIFLAG_START;
175 ++tri;
177 U1(*tri).v1 = base_idx + 2;
178 U2(*tri).v2 = base_idx + 1;
179 U3(*tri).v3 = base_idx + 3;
180 tri->wFlags = D3DTRIFLAG_ODD;
181 ++tri;
183 *ptr = tri;
186 static void emit_end(void **ptr)
188 D3DINSTRUCTION *inst = *ptr;
190 inst->bOpcode = D3DOP_EXIT;
191 inst->bSize = 0;
192 inst->wCount = 0;
194 *ptr = inst + 1;
197 static void set_execute_data(IDirect3DExecuteBuffer *execute_buffer, UINT vertex_count, UINT offset, UINT len)
199 D3DEXECUTEDATA exec_data;
200 HRESULT hr;
202 memset(&exec_data, 0, sizeof(exec_data));
203 exec_data.dwSize = sizeof(exec_data);
204 exec_data.dwVertexCount = vertex_count;
205 exec_data.dwInstructionOffset = offset;
206 exec_data.dwInstructionLength = len;
207 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
208 ok(SUCCEEDED(hr), "Failed to set execute data, hr %#x.\n", hr);
211 static DWORD get_device_z_depth(IDirect3DDevice *device)
213 DDSCAPS caps = {DDSCAPS_ZBUFFER};
214 IDirectDrawSurface *ds, *rt;
215 DDSURFACEDESC desc;
216 HRESULT hr;
218 if (FAILED(IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt)))
219 return 0;
221 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ds);
222 IDirectDrawSurface_Release(rt);
223 if (FAILED(hr))
224 return 0;
226 desc.dwSize = sizeof(desc);
227 hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
228 IDirectDrawSurface_Release(ds);
229 if (FAILED(hr))
230 return 0;
232 return U2(desc).dwZBufferBitDepth;
235 static IDirectDraw *create_ddraw(void)
237 IDirectDraw *ddraw;
239 if (FAILED(DirectDrawCreate(NULL, &ddraw, NULL)))
240 return NULL;
242 return ddraw;
245 static IDirect3DDevice *create_device(IDirectDraw *ddraw, HWND window, DWORD coop_level)
247 static const DWORD z_depths[] = {32, 24, 16};
248 IDirectDrawSurface *surface, *ds;
249 IDirect3DDevice *device = NULL;
250 DDSURFACEDESC surface_desc;
251 unsigned int i;
252 HRESULT hr;
254 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, coop_level);
255 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
257 memset(&surface_desc, 0, sizeof(surface_desc));
258 surface_desc.dwSize = sizeof(surface_desc);
259 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
260 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
261 surface_desc.dwWidth = 640;
262 surface_desc.dwHeight = 480;
264 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
265 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
267 if (coop_level & DDSCL_NORMAL)
269 IDirectDrawClipper *clipper;
271 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
272 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
273 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
274 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
275 hr = IDirectDrawSurface_SetClipper(surface, clipper);
276 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
277 IDirectDrawClipper_Release(clipper);
280 /* We used to use EnumDevices() for this, but it seems
281 * D3DDEVICEDESC.dwDeviceZBufferBitDepth only has a very casual
282 * relationship with reality. */
283 for (i = 0; i < sizeof(z_depths) / sizeof(*z_depths); ++i)
285 memset(&surface_desc, 0, sizeof(surface_desc));
286 surface_desc.dwSize = sizeof(surface_desc);
287 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
288 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
289 U2(surface_desc).dwZBufferBitDepth = z_depths[i];
290 surface_desc.dwWidth = 640;
291 surface_desc.dwHeight = 480;
292 if (FAILED(hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL)))
293 continue;
295 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
296 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
297 IDirectDrawSurface_Release(ds);
298 if (FAILED(hr))
299 continue;
301 if (SUCCEEDED(hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device)))
302 break;
304 IDirectDrawSurface_DeleteAttachedSurface(surface, 0, ds);
307 IDirectDrawSurface_Release(surface);
308 return device;
311 static IDirect3DViewport *create_viewport(IDirect3DDevice *device, UINT x, UINT y, UINT w, UINT h)
313 IDirect3DViewport *viewport;
314 D3DVIEWPORT vp;
315 IDirect3D *d3d;
316 HRESULT hr;
318 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
319 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
320 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
321 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
322 hr = IDirect3DDevice_AddViewport(device, viewport);
323 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
324 memset(&vp, 0, sizeof(vp));
325 vp.dwSize = sizeof(vp);
326 vp.dwX = x;
327 vp.dwY = y;
328 vp.dwWidth = w;
329 vp.dwHeight = h;
330 vp.dvScaleX = (float)w / 2.0f;
331 vp.dvScaleY = (float)h / 2.0f;
332 vp.dvMaxX = 1.0f;
333 vp.dvMaxY = 1.0f;
334 vp.dvMinZ = 0.0f;
335 vp.dvMaxZ = 1.0f;
336 hr = IDirect3DViewport_SetViewport(viewport, &vp);
337 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
338 IDirect3D_Release(d3d);
340 return viewport;
343 static void viewport_set_background(IDirect3DDevice *device, IDirect3DViewport *viewport,
344 IDirect3DMaterial *material)
346 D3DMATERIALHANDLE material_handle;
347 HRESULT hr;
349 hr = IDirect3DMaterial2_GetHandle(material, device, &material_handle);
350 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
351 hr = IDirect3DViewport2_SetBackground(viewport, material_handle);
352 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
355 static void destroy_viewport(IDirect3DDevice *device, IDirect3DViewport *viewport)
357 HRESULT hr;
359 hr = IDirect3DDevice_DeleteViewport(device, viewport);
360 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
361 IDirect3DViewport_Release(viewport);
364 static IDirect3DMaterial *create_diffuse_material(IDirect3DDevice *device, float r, float g, float b, float a)
366 IDirect3DMaterial *material;
367 D3DMATERIAL mat;
368 IDirect3D *d3d;
369 HRESULT hr;
371 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
372 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
373 hr = IDirect3D_CreateMaterial(d3d, &material, NULL);
374 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
375 memset(&mat, 0, sizeof(mat));
376 mat.dwSize = sizeof(mat);
377 U1(U(mat).diffuse).r = r;
378 U2(U(mat).diffuse).g = g;
379 U3(U(mat).diffuse).b = b;
380 U4(U(mat).diffuse).a = a;
381 hr = IDirect3DMaterial_SetMaterial(material, &mat);
382 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
383 IDirect3D_Release(d3d);
385 return material;
388 static void destroy_material(IDirect3DMaterial *material)
390 IDirect3DMaterial_Release(material);
393 static const UINT *expect_messages;
395 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
397 if (expect_messages && message == *expect_messages)
398 ++expect_messages;
400 return DefWindowProcA(hwnd, message, wparam, lparam);
403 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
404 * interface. This prevents subsequent SetCooperativeLevel() calls on a
405 * different window from failing with DDERR_HWNDALREADYSET. */
406 static void fix_wndproc(HWND window, LONG_PTR proc)
408 IDirectDraw *ddraw;
409 HRESULT hr;
411 if (!(ddraw = create_ddraw()))
412 return;
414 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
415 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
416 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
417 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
418 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
420 IDirectDraw_Release(ddraw);
423 static HRESULT CALLBACK restore_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
425 HRESULT hr = IDirectDrawSurface_Restore(surface);
426 ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
427 IDirectDrawSurface_Release(surface);
429 return DDENUMRET_OK;
432 static HRESULT restore_surfaces(IDirectDraw *ddraw)
434 return IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
435 NULL, NULL, restore_callback);
438 static void test_coop_level_create_device_window(void)
440 HWND focus_window, device_window;
441 IDirectDraw *ddraw;
442 HRESULT hr;
444 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
445 0, 0, 640, 480, 0, 0, 0, 0);
446 ddraw = create_ddraw();
447 ok(!!ddraw, "Failed to create a ddraw object.\n");
449 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
450 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
451 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
452 ok(!device_window, "Unexpected device window found.\n");
453 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
454 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
455 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
456 ok(!device_window, "Unexpected device window found.\n");
457 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
458 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
459 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
460 ok(!device_window, "Unexpected device window found.\n");
461 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
462 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
463 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
464 ok(!device_window, "Unexpected device window found.\n");
465 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
466 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
467 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
468 ok(!device_window, "Unexpected device window found.\n");
470 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
471 if (broken(hr == DDERR_INVALIDPARAMS))
473 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
474 IDirectDraw_Release(ddraw);
475 DestroyWindow(focus_window);
476 return;
479 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
480 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
481 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
482 ok(!device_window, "Unexpected device window found.\n");
483 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
484 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
485 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
486 ok(!device_window, "Unexpected device window found.\n");
488 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
489 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
490 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
491 ok(!device_window, "Unexpected device window found.\n");
492 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
493 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
494 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
495 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
496 ok(!!device_window, "Device window not found.\n");
498 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
499 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
500 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
501 ok(!device_window, "Unexpected device window found.\n");
502 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
503 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
504 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
505 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
506 ok(!!device_window, "Device window not found.\n");
508 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
509 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
510 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
511 ok(!device_window, "Unexpected device window found.\n");
512 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
513 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
514 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
515 ok(!device_window, "Unexpected device window found.\n");
516 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
517 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
518 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
519 ok(!device_window, "Unexpected device window found.\n");
520 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
521 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
522 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
523 ok(!!device_window, "Device window not found.\n");
525 IDirectDraw_Release(ddraw);
526 DestroyWindow(focus_window);
529 static void test_clipper_blt(void)
531 IDirectDrawSurface *src_surface, *dst_surface;
532 RECT client_rect, src_rect;
533 IDirectDrawClipper *clipper;
534 DDSURFACEDESC surface_desc;
535 unsigned int i, j, x, y;
536 IDirectDraw *ddraw;
537 RGNDATA *rgn_data;
538 D3DCOLOR color;
539 HRGN r1, r2;
540 HWND window;
541 DDBLTFX fx;
542 HRESULT hr;
543 DWORD *ptr;
544 DWORD ret;
546 static const DWORD src_data[] =
548 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
549 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
550 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
552 static const D3DCOLOR expected1[] =
554 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
555 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
556 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
557 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
559 /* Nvidia on Windows seems to have an off-by-one error
560 * when processing source rectangles. Our left = 1 and
561 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
562 * read as well, but only for the edge pixels on the
563 * output image. The bug happens on the y axis as well,
564 * but we only read one row there, and all source rows
565 * contain the same data. This bug is not dependent on
566 * the presence of a clipper. */
567 static const D3DCOLOR expected1_broken[] =
569 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
570 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
571 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
572 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
574 static const D3DCOLOR expected2[] =
576 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
577 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
578 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
579 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
582 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
583 10, 10, 640, 480, 0, 0, 0, 0);
584 ShowWindow(window, SW_SHOW);
585 ddraw = create_ddraw();
586 ok(!!ddraw, "Failed to create a ddraw object.\n");
588 ret = GetClientRect(window, &client_rect);
589 ok(ret, "Failed to get client rect.\n");
590 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
591 ok(ret, "Failed to map client rect.\n");
593 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
594 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
596 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
597 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
598 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
599 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
600 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
601 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
602 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
603 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
604 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
605 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
606 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
607 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
608 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
609 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
610 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
611 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
612 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
613 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
614 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
615 HeapFree(GetProcessHeap(), 0, rgn_data);
617 r1 = CreateRectRgn(0, 0, 320, 240);
618 ok(!!r1, "Failed to create region.\n");
619 r2 = CreateRectRgn(320, 240, 640, 480);
620 ok(!!r2, "Failed to create region.\n");
621 CombineRgn(r1, r1, r2, RGN_OR);
622 ret = GetRegionData(r1, 0, NULL);
623 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
624 ret = GetRegionData(r1, ret, rgn_data);
625 ok(!!ret, "Failed to get region data.\n");
627 DeleteObject(r2);
628 DeleteObject(r1);
630 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
631 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
632 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
633 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
634 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
635 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
637 HeapFree(GetProcessHeap(), 0, rgn_data);
639 memset(&surface_desc, 0, sizeof(surface_desc));
640 surface_desc.dwSize = sizeof(surface_desc);
641 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
642 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
643 surface_desc.dwWidth = 640;
644 surface_desc.dwHeight = 480;
645 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
646 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
647 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
648 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
649 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
650 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
652 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
653 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
654 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
655 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
657 memset(&fx, 0, sizeof(fx));
658 fx.dwSize = sizeof(fx);
659 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
660 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
661 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
662 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
664 hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
665 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
666 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
667 ptr = surface_desc.lpSurface;
668 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
669 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
670 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
671 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
672 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
674 hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
675 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
677 SetRect(&src_rect, 1, 1, 5, 2);
678 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
679 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
680 for (i = 0; i < 4; ++i)
682 for (j = 0; j < 4; ++j)
684 x = 80 * ((2 * j) + 1);
685 y = 60 * ((2 * i) + 1);
686 color = get_surface_color(dst_surface, x, y);
687 ok(compare_color(color, expected1[i * 4 + j], 1)
688 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
689 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
693 U5(fx).dwFillColor = 0xff0000ff;
694 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
695 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
696 for (i = 0; i < 4; ++i)
698 for (j = 0; j < 4; ++j)
700 x = 80 * ((2 * j) + 1);
701 y = 60 * ((2 * i) + 1);
702 color = get_surface_color(dst_surface, x, y);
703 ok(compare_color(color, expected2[i * 4 + j], 1),
704 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
708 hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
709 ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
711 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
712 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
713 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
714 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
715 DestroyWindow(window);
716 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
717 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
718 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
719 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
720 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
721 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
722 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
723 ok(SUCCEEDED(hr), "Failed to set clip list, 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 = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
727 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
729 IDirectDrawSurface_Release(dst_surface);
730 IDirectDrawSurface_Release(src_surface);
731 IDirectDrawClipper_Release(clipper);
732 IDirectDraw_Release(ddraw);
735 static void test_coop_level_d3d_state(void)
737 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
738 IDirectDrawSurface *rt, *surface;
739 IDirect3DMaterial *background;
740 IDirect3DViewport *viewport;
741 IDirect3DDevice *device;
742 D3DMATERIAL material;
743 IDirectDraw *ddraw;
744 D3DCOLOR color;
745 HWND window;
746 HRESULT hr;
748 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
749 0, 0, 640, 480, 0, 0, 0, 0);
750 ddraw = create_ddraw();
751 ok(!!ddraw, "Failed to create a ddraw object.\n");
752 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
754 skip("Failed to create a 3D device, skipping test.\n");
755 IDirectDraw_Release(ddraw);
756 DestroyWindow(window);
757 return;
760 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
761 viewport = create_viewport(device, 0, 0, 640, 480);
762 viewport_set_background(device, viewport, background);
764 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
765 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
766 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
767 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
768 color = get_surface_color(rt, 320, 240);
769 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
771 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
772 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
773 hr = IDirectDrawSurface_IsLost(rt);
774 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
775 hr = restore_surfaces(ddraw);
776 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
778 memset(&material, 0, sizeof(material));
779 material.dwSize = sizeof(material);
780 U1(U(material).diffuse).r = 0.0f;
781 U2(U(material).diffuse).g = 1.0f;
782 U3(U(material).diffuse).b = 0.0f;
783 U4(U(material).diffuse).a = 1.0f;
784 hr = IDirect3DMaterial_SetMaterial(background, &material);
785 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
787 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&surface);
788 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
789 ok(surface == rt, "Got unexpected surface %p.\n", surface);
790 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
791 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
792 color = get_surface_color(rt, 320, 240);
793 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
795 destroy_viewport(device, viewport);
796 destroy_material(background);
797 IDirectDrawSurface_Release(surface);
798 IDirectDrawSurface_Release(rt);
799 IDirect3DDevice_Release(device);
800 IDirectDraw_Release(ddraw);
801 DestroyWindow(window);
804 static void test_surface_interface_mismatch(void)
806 IDirectDraw *ddraw = NULL;
807 IDirectDrawSurface *surface = NULL, *ds;
808 IDirectDrawSurface3 *surface3 = NULL;
809 IDirect3DDevice *device = NULL;
810 IDirect3DViewport *viewport = NULL;
811 IDirect3DMaterial *background = NULL;
812 DDSURFACEDESC surface_desc;
813 DWORD z_depth = 0;
814 ULONG refcount;
815 HRESULT hr;
816 D3DCOLOR color;
817 HWND window;
818 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
820 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
821 0, 0, 640, 480, 0, 0, 0, 0);
822 ddraw = create_ddraw();
823 ok(!!ddraw, "Failed to create a ddraw object.\n");
824 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
826 skip("Failed to create a 3D device, skipping test.\n");
827 IDirectDraw_Release(ddraw);
828 DestroyWindow(window);
829 return;
831 z_depth = get_device_z_depth(device);
832 ok(!!z_depth, "Failed to get device z depth.\n");
833 IDirect3DDevice_Release(device);
834 device = NULL;
836 memset(&surface_desc, 0, sizeof(surface_desc));
837 surface_desc.dwSize = sizeof(surface_desc);
838 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
839 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
840 surface_desc.dwWidth = 640;
841 surface_desc.dwHeight = 480;
843 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
844 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
846 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
847 if (FAILED(hr))
849 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
850 goto cleanup;
853 memset(&surface_desc, 0, sizeof(surface_desc));
854 surface_desc.dwSize = sizeof(surface_desc);
855 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
856 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
857 U2(surface_desc).dwZBufferBitDepth = z_depth;
858 surface_desc.dwWidth = 640;
859 surface_desc.dwHeight = 480;
860 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL);
861 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
862 if (FAILED(hr))
863 goto cleanup;
865 /* Using a different surface interface version still works */
866 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
867 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
868 refcount = IDirectDrawSurface_Release(ds);
869 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
870 if (FAILED(hr))
871 goto cleanup;
873 /* Here too */
874 hr = IDirectDrawSurface3_QueryInterface(surface3, &IID_IDirect3DHALDevice, (void **)&device);
875 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
876 if (FAILED(hr))
877 goto cleanup;
879 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
880 viewport = create_viewport(device, 0, 0, 640, 480);
881 viewport_set_background(device, viewport, background);
883 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
884 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
885 color = get_surface_color(surface, 320, 240);
886 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
888 cleanup:
889 if (viewport)
890 destroy_viewport(device, viewport);
891 if (background)
892 destroy_material(background);
893 if (surface3) IDirectDrawSurface3_Release(surface3);
894 if (surface) IDirectDrawSurface_Release(surface);
895 if (device) IDirect3DDevice_Release(device);
896 if (ddraw) IDirectDraw_Release(ddraw);
897 DestroyWindow(window);
900 static void test_coop_level_threaded(void)
902 struct create_window_thread_param p;
903 IDirectDraw *ddraw;
904 HRESULT hr;
906 ddraw = create_ddraw();
907 ok(!!ddraw, "Failed to create a ddraw object.\n");
908 create_window_thread(&p);
910 hr = IDirectDraw_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
911 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
913 IDirectDraw_Release(ddraw);
914 destroy_window_thread(&p);
917 static ULONG get_refcount(IUnknown *test_iface)
919 IUnknown_AddRef(test_iface);
920 return IUnknown_Release(test_iface);
923 static void test_viewport(void)
925 IDirectDraw *ddraw;
926 IDirect3D *d3d;
927 HRESULT hr;
928 ULONG ref;
929 IDirect3DViewport *viewport, *another_vp;
930 IDirect3DViewport2 *viewport2;
931 IDirect3DViewport3 *viewport3;
932 IDirectDrawGammaControl *gamma;
933 IUnknown *unknown;
934 IDirect3DDevice *device;
935 HWND window;
937 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
938 0, 0, 640, 480, 0, 0, 0, 0);
939 ddraw = create_ddraw();
940 ok(!!ddraw, "Failed to create a ddraw object.\n");
941 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
943 skip("Failed to create a 3D device, skipping test.\n");
944 IDirectDraw_Release(ddraw);
945 DestroyWindow(window);
946 return;
949 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
950 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
951 ref = get_refcount((IUnknown *) d3d);
952 ok(ref == 2, "IDirect3D refcount is %d\n", ref);
954 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
955 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
956 ref = get_refcount((IUnknown *)viewport);
957 ok(ref == 1, "Initial IDirect3DViewport refcount is %u\n", ref);
958 ref = get_refcount((IUnknown *)d3d);
959 ok(ref == 2, "IDirect3D refcount is %u\n", ref);
961 /* E_FAIL return values are returned by Winetestbot Windows NT machines. While not supporting
962 * newer interfaces is legitimate for old ddraw versions, E_FAIL violates Microsoft's rules
963 * for QueryInterface, hence the broken() */
964 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
965 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirectDrawGammaControl, (void **)&gamma);
966 ok(hr == E_NOINTERFACE || broken(hr == E_FAIL), "Got unexpected hr %#x.\n", hr);
967 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
968 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
969 /* NULL iid: Segfaults */
971 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport2, (void **)&viewport2);
972 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
973 "Failed to QI IDirect3DViewport2, hr %#x.\n", hr);
974 if (viewport2)
976 ref = get_refcount((IUnknown *)viewport);
977 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
978 ref = get_refcount((IUnknown *)viewport2);
979 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
980 IDirect3DViewport2_Release(viewport2);
981 viewport2 = NULL;
984 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport3, (void **)&viewport3);
985 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
986 "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
987 if (viewport3)
989 ref = get_refcount((IUnknown *)viewport);
990 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
991 ref = get_refcount((IUnknown *)viewport3);
992 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
993 IDirect3DViewport3_Release(viewport3);
996 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IUnknown, (void **)&unknown);
997 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
998 if (unknown)
1000 ref = get_refcount((IUnknown *)viewport);
1001 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1002 ref = get_refcount(unknown);
1003 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1004 IUnknown_Release(unknown);
1007 /* AddViewport(NULL): Segfault */
1008 hr = IDirect3DDevice_DeleteViewport(device, NULL);
1009 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1011 hr = IDirect3D_CreateViewport(d3d, &another_vp, NULL);
1012 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1014 hr = IDirect3DDevice_AddViewport(device, viewport);
1015 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1016 ref = get_refcount((IUnknown *) viewport);
1017 ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
1018 hr = IDirect3DDevice_AddViewport(device, another_vp);
1019 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1020 ref = get_refcount((IUnknown *) another_vp);
1021 ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
1023 hr = IDirect3DDevice_DeleteViewport(device, another_vp);
1024 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1025 ref = get_refcount((IUnknown *) another_vp);
1026 ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
1028 IDirect3DDevice_Release(device);
1029 ref = get_refcount((IUnknown *) viewport);
1030 ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
1032 IDirect3DViewport_Release(another_vp);
1033 IDirect3D_Release(d3d);
1034 IDirect3DViewport_Release(viewport);
1035 DestroyWindow(window);
1036 IDirectDraw_Release(ddraw);
1039 static void test_zenable(void)
1041 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1042 static D3DTLVERTEX tquad[] =
1044 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1045 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1046 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1047 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1049 IDirect3DExecuteBuffer *execute_buffer;
1050 D3DEXECUTEBUFFERDESC exec_desc;
1051 IDirect3DMaterial *background;
1052 IDirect3DViewport *viewport;
1053 IDirect3DDevice *device;
1054 IDirectDrawSurface *rt;
1055 IDirectDraw *ddraw;
1056 UINT inst_length;
1057 D3DCOLOR color;
1058 HWND window;
1059 HRESULT hr;
1060 UINT x, y;
1061 UINT i, j;
1062 void *ptr;
1064 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1065 0, 0, 640, 480, 0, 0, 0, 0);
1066 ddraw = create_ddraw();
1067 ok(!!ddraw, "Failed to create a ddraw object.\n");
1068 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1070 skip("Failed to create a 3D device, skipping test.\n");
1071 IDirectDraw_Release(ddraw);
1072 DestroyWindow(window);
1073 return;
1076 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1077 viewport = create_viewport(device, 0, 0, 640, 480);
1078 viewport_set_background(device, viewport, background);
1080 memset(&exec_desc, 0, sizeof(exec_desc));
1081 exec_desc.dwSize = sizeof(exec_desc);
1082 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1083 exec_desc.dwBufferSize = 1024;
1084 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1086 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1087 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1088 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1089 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1090 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1091 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1092 emit_process_vertices(&ptr, 0, 4);
1093 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1094 emit_tquad(&ptr, 0);
1095 emit_end(&ptr);
1096 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
1097 inst_length -= sizeof(tquad);
1098 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1099 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1101 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1102 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1103 hr = IDirect3DDevice_BeginScene(device);
1104 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1105 set_execute_data(execute_buffer, 4, sizeof(tquad), inst_length);
1106 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1107 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1108 hr = IDirect3DDevice_EndScene(device);
1109 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1111 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1112 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1113 for (i = 0; i < 4; ++i)
1115 for (j = 0; j < 4; ++j)
1117 x = 80 * ((2 * j) + 1);
1118 y = 60 * ((2 * i) + 1);
1119 color = get_surface_color(rt, x, y);
1120 ok(compare_color(color, 0x0000ff00, 1),
1121 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1124 IDirectDrawSurface_Release(rt);
1126 destroy_viewport(device, viewport);
1127 IDirect3DExecuteBuffer_Release(execute_buffer);
1128 destroy_material(background);
1129 IDirect3DDevice_Release(device);
1130 IDirectDraw_Release(ddraw);
1131 DestroyWindow(window);
1134 static void test_ck_rgba(void)
1136 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1137 static D3DTLVERTEX tquad[] =
1139 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1140 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1141 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1142 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1143 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1144 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1145 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1146 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1148 static const struct
1150 D3DCOLOR fill_color;
1151 BOOL color_key;
1152 BOOL blend;
1153 D3DCOLOR result1;
1154 D3DCOLOR result2;
1156 tests[] =
1158 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x000000ff},
1159 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x000000ff},
1160 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00},
1161 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1162 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00807f00},
1163 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x0000ff00},
1164 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00},
1165 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1168 IDirect3DExecuteBuffer *execute_buffer;
1169 D3DTEXTUREHANDLE texture_handle;
1170 D3DEXECUTEBUFFERDESC exec_desc;
1171 IDirect3DMaterial *background;
1172 IDirectDrawSurface *surface;
1173 IDirect3DViewport *viewport;
1174 DDSURFACEDESC surface_desc;
1175 IDirect3DTexture *texture;
1176 IDirect3DDevice *device;
1177 IDirectDrawSurface *rt;
1178 IDirectDraw *ddraw;
1179 D3DCOLOR color;
1180 HWND window;
1181 DDBLTFX fx;
1182 HRESULT hr;
1183 UINT i;
1185 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1186 0, 0, 640, 480, 0, 0, 0, 0);
1187 ddraw = create_ddraw();
1188 ok(!!ddraw, "Failed to create a ddraw object.\n");
1189 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1191 skip("Failed to create a 3D device, skipping test.\n");
1192 IDirectDraw_Release(ddraw);
1193 DestroyWindow(window);
1194 return;
1197 background = create_diffuse_material(device, 1.0, 0.0f, 0.0f, 1.0f);
1198 viewport = create_viewport(device, 0, 0, 640, 480);
1199 viewport_set_background(device, viewport, background);
1201 memset(&surface_desc, 0, sizeof(surface_desc));
1202 surface_desc.dwSize = sizeof(surface_desc);
1203 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1204 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1205 surface_desc.dwWidth = 256;
1206 surface_desc.dwHeight = 256;
1207 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1208 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1209 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1210 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1211 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1212 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1213 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1214 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1215 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1216 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1217 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1218 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1219 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1220 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1221 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1222 IDirect3DTexture_Release(texture);
1224 memset(&exec_desc, 0, sizeof(exec_desc));
1225 exec_desc.dwSize = sizeof(exec_desc);
1226 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1227 exec_desc.dwBufferSize = 1024;
1228 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1229 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1230 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1232 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1233 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1235 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1237 UINT draw1_len, draw2_len;
1238 void *ptr;
1240 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1241 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1242 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1243 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1244 emit_process_vertices(&ptr, 0, 4);
1245 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1246 emit_set_rs(&ptr, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1247 emit_set_rs(&ptr, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1248 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1249 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1250 emit_tquad(&ptr, 0);
1251 emit_end(&ptr);
1252 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - sizeof(tquad);
1253 emit_process_vertices(&ptr, 4, 4);
1254 emit_tquad(&ptr, 0);
1255 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1256 emit_end(&ptr);
1257 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_len;
1258 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1259 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1261 memset(&fx, 0, sizeof(fx));
1262 fx.dwSize = sizeof(fx);
1263 U5(fx).dwFillColor = tests[i].fill_color;
1264 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1265 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1267 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1268 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1269 hr = IDirect3DDevice_BeginScene(device);
1270 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1271 set_execute_data(execute_buffer, 8, sizeof(tquad), draw1_len);
1272 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1273 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1274 hr = IDirect3DDevice_EndScene(device);
1275 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1277 color = get_surface_color(rt, 320, 240);
1278 if (i == 2)
1279 todo_wine ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1280 tests[i].result1, i, color);
1281 else
1282 ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1283 tests[i].result1, i, color);
1285 U5(fx).dwFillColor = 0xff0000ff;
1286 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1287 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1289 hr = IDirect3DDevice_BeginScene(device);
1290 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1291 set_execute_data(execute_buffer, 8, sizeof(tquad) + draw1_len, draw2_len);
1292 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1293 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1294 hr = IDirect3DDevice_EndScene(device);
1295 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1297 /* This tests that fragments that are masked out by the color key are
1298 * discarded, instead of just fully transparent. */
1299 color = get_surface_color(rt, 320, 240);
1300 if (i == 2)
1301 todo_wine ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1302 tests[i].result2, i, color);
1303 else
1304 ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1305 tests[i].result2, i, color);
1308 IDirectDrawSurface_Release(rt);
1309 IDirect3DExecuteBuffer_Release(execute_buffer);
1310 IDirectDrawSurface_Release(surface);
1311 destroy_viewport(device, viewport);
1312 destroy_material(background);
1313 IDirect3DDevice_Release(device);
1314 IDirectDraw_Release(ddraw);
1315 DestroyWindow(window);
1318 static void test_ck_default(void)
1320 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1321 static D3DTLVERTEX tquad[] =
1323 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1324 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1325 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1326 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1328 IDirect3DExecuteBuffer *execute_buffer;
1329 IDirectDrawSurface *surface, *rt;
1330 D3DTEXTUREHANDLE texture_handle;
1331 D3DEXECUTEBUFFERDESC exec_desc;
1332 IDirect3DMaterial *background;
1333 UINT draw1_offset, draw1_len;
1334 UINT draw2_offset, draw2_len;
1335 UINT draw3_offset, draw3_len;
1336 UINT draw4_offset, draw4_len;
1337 IDirect3DViewport *viewport;
1338 DDSURFACEDESC surface_desc;
1339 IDirect3DTexture *texture;
1340 IDirect3DDevice *device;
1341 IDirectDraw *ddraw;
1342 D3DCOLOR color;
1343 HWND window;
1344 DDBLTFX fx;
1345 HRESULT hr;
1346 void *ptr;
1348 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1349 0, 0, 640, 480, 0, 0, 0, 0);
1350 ddraw = create_ddraw();
1351 ok(!!ddraw, "Failed to create a ddraw object.\n");
1352 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1354 skip("Failed to create a 3D device, skipping test.\n");
1355 IDirectDraw_Release(ddraw);
1356 DestroyWindow(window);
1357 return;
1360 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1361 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1363 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
1364 viewport = create_viewport(device, 0, 0, 640, 480);
1365 viewport_set_background(device, viewport, background);
1367 memset(&surface_desc, 0, sizeof(surface_desc));
1368 surface_desc.dwSize = sizeof(surface_desc);
1369 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1370 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1371 surface_desc.dwWidth = 256;
1372 surface_desc.dwHeight = 256;
1373 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1374 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1375 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1376 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1377 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1378 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1379 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1380 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1381 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1382 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1383 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1384 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1385 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1386 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1387 IDirect3DTexture_Release(texture);
1389 memset(&fx, 0, sizeof(fx));
1390 fx.dwSize = sizeof(fx);
1391 U5(fx).dwFillColor = 0x000000ff;
1392 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1393 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1395 memset(&exec_desc, 0, sizeof(exec_desc));
1396 exec_desc.dwSize = sizeof(exec_desc);
1397 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1398 exec_desc.dwBufferSize = 1024;
1399 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1400 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1401 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1403 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1404 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1405 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1406 ptr = (BYTE *)exec_desc.lpData + sizeof(tquad);
1407 emit_process_vertices(&ptr, 0, 4);
1408 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1409 emit_tquad(&ptr, 0);
1410 emit_end(&ptr);
1411 draw1_offset = sizeof(tquad);
1412 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_offset;
1413 emit_process_vertices(&ptr, 0, 4);
1414 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, FALSE);
1415 emit_tquad(&ptr, 0);
1416 emit_end(&ptr);
1417 draw2_offset = draw1_offset + draw1_len;
1418 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw2_offset;
1419 emit_process_vertices(&ptr, 0, 4);
1420 emit_tquad(&ptr, 0);
1421 emit_end(&ptr);
1422 draw3_offset = draw2_offset + draw2_len;
1423 draw3_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw3_offset;
1424 emit_process_vertices(&ptr, 0, 4);
1425 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1426 emit_tquad(&ptr, 0);
1427 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1428 emit_end(&ptr);
1429 draw4_offset = draw3_offset + draw3_len;
1430 draw4_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw4_offset;
1431 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1432 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1434 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1435 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1436 hr = IDirect3DDevice_BeginScene(device);
1437 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1438 set_execute_data(execute_buffer, 4, draw1_offset, draw1_len);
1439 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1440 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1441 hr = IDirect3DDevice_EndScene(device);
1442 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1443 color = get_surface_color(rt, 320, 240);
1444 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1446 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1447 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1448 hr = IDirect3DDevice_BeginScene(device);
1449 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1450 set_execute_data(execute_buffer, 4, draw2_offset, draw2_len);
1451 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1452 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1453 hr = IDirect3DDevice_EndScene(device);
1454 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1455 color = get_surface_color(rt, 320, 240);
1456 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1458 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1459 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1460 hr = IDirect3DDevice_BeginScene(device);
1461 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1462 set_execute_data(execute_buffer, 4, draw3_offset, draw3_len);
1463 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1464 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1465 hr = IDirect3DDevice_EndScene(device);
1466 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1467 color = get_surface_color(rt, 320, 240);
1468 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1470 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1471 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1472 hr = IDirect3DDevice_BeginScene(device);
1473 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1474 set_execute_data(execute_buffer, 4, draw4_offset, draw4_len);
1475 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1476 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1477 hr = IDirect3DDevice_EndScene(device);
1478 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1479 color = get_surface_color(rt, 320, 240);
1480 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1482 IDirect3DExecuteBuffer_Release(execute_buffer);
1483 IDirectDrawSurface_Release(surface);
1484 destroy_viewport(device, viewport);
1485 destroy_material(background);
1486 IDirectDrawSurface_Release(rt);
1487 IDirect3DDevice_Release(device);
1488 IDirectDraw_Release(ddraw);
1489 DestroyWindow(window);
1492 static void test_ck_complex(void)
1494 IDirectDrawSurface *surface, *mipmap, *tmp;
1495 DDSCAPS caps = {DDSCAPS_COMPLEX};
1496 DDSURFACEDESC surface_desc;
1497 IDirect3DDevice *device;
1498 DDCOLORKEY color_key;
1499 IDirectDraw *ddraw;
1500 unsigned int i;
1501 ULONG refcount;
1502 HWND window;
1503 HRESULT hr;
1505 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1506 0, 0, 640, 480, 0, 0, 0, 0);
1507 ddraw = create_ddraw();
1508 ok(!!ddraw, "Failed to create a ddraw object.\n");
1509 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1511 skip("Failed to create a 3D device, skipping test.\n");
1512 DestroyWindow(window);
1513 IDirectDraw2_Release(ddraw);
1514 return;
1516 IDirect3DDevice_Release(device);
1518 memset(&surface_desc, 0, sizeof(surface_desc));
1519 surface_desc.dwSize = sizeof(surface_desc);
1520 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1521 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1522 surface_desc.dwWidth = 128;
1523 surface_desc.dwHeight = 128;
1524 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1525 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1527 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1528 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1529 color_key.dwColorSpaceLowValue = 0x0000ff00;
1530 color_key.dwColorSpaceHighValue = 0x0000ff00;
1531 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1532 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1533 memset(&color_key, 0, sizeof(color_key));
1534 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1535 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1536 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1537 color_key.dwColorSpaceLowValue);
1538 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1539 color_key.dwColorSpaceHighValue);
1541 mipmap = surface;
1542 IDirectDrawSurface_AddRef(mipmap);
1543 for (i = 0; i < 7; ++i)
1545 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1546 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1548 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1549 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1550 color_key.dwColorSpaceLowValue = 0x000000ff;
1551 color_key.dwColorSpaceHighValue = 0x000000ff;
1552 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1553 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x, i %u.\n", hr, i);
1554 memset(&color_key, 0, sizeof(color_key));
1555 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1556 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x, i %u.\n", hr, i);
1557 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1558 color_key.dwColorSpaceLowValue, i);
1559 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1560 color_key.dwColorSpaceHighValue, i);
1562 IDirectDrawSurface_Release(mipmap);
1563 mipmap = tmp;
1566 memset(&color_key, 0, sizeof(color_key));
1567 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1568 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1569 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1570 color_key.dwColorSpaceLowValue);
1571 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1572 color_key.dwColorSpaceHighValue);
1574 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1575 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1576 IDirectDrawSurface_Release(mipmap);
1577 refcount = IDirectDrawSurface_Release(surface);
1578 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1580 memset(&surface_desc, 0, sizeof(surface_desc));
1581 surface_desc.dwSize = sizeof(surface_desc);
1582 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1583 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1584 surface_desc.dwBackBufferCount = 1;
1585 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1586 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1588 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1589 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1590 color_key.dwColorSpaceLowValue = 0x0000ff00;
1591 color_key.dwColorSpaceHighValue = 0x0000ff00;
1592 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1593 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1594 memset(&color_key, 0, sizeof(color_key));
1595 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1596 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1597 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1598 color_key.dwColorSpaceLowValue);
1599 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1600 color_key.dwColorSpaceHighValue);
1602 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
1603 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1605 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1606 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1607 color_key.dwColorSpaceLowValue = 0x0000ff00;
1608 color_key.dwColorSpaceHighValue = 0x0000ff00;
1609 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1610 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1611 memset(&color_key, 0, sizeof(color_key));
1612 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1613 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1614 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1615 color_key.dwColorSpaceLowValue);
1616 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1617 color_key.dwColorSpaceHighValue);
1619 IDirectDrawSurface_Release(tmp);
1621 refcount = IDirectDrawSurface_Release(surface);
1622 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1623 refcount = IDirectDraw_Release(ddraw);
1624 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1625 DestroyWindow(window);
1628 struct qi_test
1630 REFIID iid;
1631 REFIID refcount_iid;
1632 HRESULT hr;
1635 static void test_qi(const char *test_name, IUnknown *base_iface,
1636 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1638 ULONG refcount, expected_refcount;
1639 IUnknown *iface1, *iface2;
1640 HRESULT hr;
1641 UINT i, j;
1643 for (i = 0; i < entry_count; ++i)
1645 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1646 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1647 if (SUCCEEDED(hr))
1649 for (j = 0; j < entry_count; ++j)
1651 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1652 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1653 if (SUCCEEDED(hr))
1655 expected_refcount = 0;
1656 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1657 ++expected_refcount;
1658 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1659 ++expected_refcount;
1660 refcount = IUnknown_Release(iface2);
1661 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1662 refcount, test_name, i, j, expected_refcount);
1666 expected_refcount = 0;
1667 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1668 ++expected_refcount;
1669 refcount = IUnknown_Release(iface1);
1670 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1671 refcount, test_name, i, expected_refcount);
1676 static void test_surface_qi(void)
1678 static const struct qi_test tests[] =
1680 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1681 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1682 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1683 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1684 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1685 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1686 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1687 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1688 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1689 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1690 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1691 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1692 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1693 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1694 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1695 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1696 {&IID_IDirect3D, NULL, E_INVALIDARG },
1697 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1698 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1699 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1700 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1701 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1702 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1703 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1704 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1705 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1706 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1707 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1708 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1709 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1710 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1711 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1712 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1713 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1714 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1717 IDirectDrawSurface *surface;
1718 DDSURFACEDESC surface_desc;
1719 IDirect3DDevice *device;
1720 IDirectDraw *ddraw;
1721 HWND window;
1722 HRESULT hr;
1724 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1726 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1727 return;
1730 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1731 0, 0, 640, 480, 0, 0, 0, 0);
1732 ddraw = create_ddraw();
1733 ok(!!ddraw, "Failed to create a ddraw object.\n");
1734 /* Try to create a D3D device to see if the ddraw implementation supports
1735 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1736 * doesn't support e.g. the IDirect3DTexture interfaces. */
1737 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1739 skip("Failed to create a 3D device, skipping test.\n");
1740 IDirectDraw_Release(ddraw);
1741 DestroyWindow(window);
1742 return;
1744 IDirect3DDevice_Release(device);
1746 memset(&surface_desc, 0, sizeof(surface_desc));
1747 surface_desc.dwSize = sizeof(surface_desc);
1748 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1749 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1750 surface_desc.dwWidth = 512;
1751 surface_desc.dwHeight = 512;
1752 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1753 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1755 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1757 IDirectDrawSurface_Release(surface);
1758 IDirectDraw_Release(ddraw);
1759 DestroyWindow(window);
1762 static void test_device_qi(void)
1764 static const struct qi_test tests[] =
1766 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1767 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1768 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1769 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1770 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1771 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1772 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1773 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1774 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1775 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1776 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1777 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1778 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1779 {&IID_IDirect3DHALDevice, &IID_IDirectDrawSurface, S_OK },
1780 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1781 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1782 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1783 {&IID_IDirect3D, NULL, E_INVALIDARG },
1784 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1785 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1786 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1787 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1788 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1789 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1790 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1791 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1792 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1793 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1794 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1795 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1796 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1797 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1798 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1799 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1800 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1801 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1805 IDirect3DDevice *device;
1806 IDirectDraw *ddraw;
1807 HWND window;
1809 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1811 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1812 return;
1815 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1816 0, 0, 640, 480, 0, 0, 0, 0);
1817 ddraw = create_ddraw();
1818 ok(!!ddraw, "Failed to create a ddraw object.\n");
1819 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1821 skip("Failed to create a 3D device, skipping test.\n");
1822 IDirectDraw_Release(ddraw);
1823 DestroyWindow(window);
1824 return;
1827 test_qi("device_qi", (IUnknown *)device, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1829 IDirect3DDevice_Release(device);
1830 IDirectDraw_Release(ddraw);
1831 DestroyWindow(window);
1834 static void test_wndproc(void)
1836 LONG_PTR proc, ddraw_proc;
1837 IDirectDraw *ddraw;
1838 WNDCLASSA wc = {0};
1839 HWND window;
1840 HRESULT hr;
1841 ULONG ref;
1843 static const UINT messages[] =
1845 WM_WINDOWPOSCHANGING,
1846 WM_MOVE,
1847 WM_SIZE,
1848 WM_WINDOWPOSCHANGING,
1849 WM_ACTIVATE,
1850 WM_SETFOCUS,
1854 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
1855 ddraw = create_ddraw();
1856 ok(!!ddraw, "Failed to create a ddraw object.\n");
1858 wc.lpfnWndProc = test_proc;
1859 wc.lpszClassName = "ddraw_test_wndproc_wc";
1860 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1862 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
1863 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
1865 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1866 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1867 (LONG_PTR)test_proc, proc);
1868 expect_messages = messages;
1869 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1870 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1871 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
1872 expect_messages = NULL;
1873 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1874 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1875 (LONG_PTR)test_proc, proc);
1876 ref = IDirectDraw_Release(ddraw);
1877 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1878 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1879 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1880 (LONG_PTR)test_proc, proc);
1882 /* DDSCL_NORMAL doesn't. */
1883 ddraw = create_ddraw();
1884 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1885 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1886 (LONG_PTR)test_proc, proc);
1887 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
1888 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1889 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1890 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1891 (LONG_PTR)test_proc, proc);
1892 ref = IDirectDraw_Release(ddraw);
1893 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1894 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1895 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1896 (LONG_PTR)test_proc, proc);
1898 /* The original window proc is only restored by ddraw if the current
1899 * window proc matches the one ddraw set. This also affects switching
1900 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
1901 ddraw = create_ddraw();
1902 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1903 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1904 (LONG_PTR)test_proc, proc);
1905 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1906 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1907 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1908 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1909 (LONG_PTR)test_proc, proc);
1910 ddraw_proc = proc;
1911 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1912 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1913 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1914 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1915 (LONG_PTR)test_proc, proc);
1916 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1917 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1918 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1919 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1920 (LONG_PTR)test_proc, proc);
1921 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1922 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1923 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1924 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1925 (LONG_PTR)DefWindowProcA, proc);
1926 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1927 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1928 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
1929 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1930 (LONG_PTR)DefWindowProcA, proc);
1931 ref = IDirectDraw_Release(ddraw);
1932 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1933 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1934 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1935 (LONG_PTR)test_proc, proc);
1937 ddraw = create_ddraw();
1938 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1939 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1940 (LONG_PTR)test_proc, proc);
1941 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1942 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1943 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1944 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1945 (LONG_PTR)test_proc, proc);
1946 ref = IDirectDraw_Release(ddraw);
1947 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1948 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1949 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1950 (LONG_PTR)DefWindowProcA, proc);
1952 fix_wndproc(window, (LONG_PTR)test_proc);
1953 expect_messages = NULL;
1954 DestroyWindow(window);
1955 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
1958 static void test_window_style(void)
1960 LONG style, exstyle, tmp;
1961 RECT fullscreen_rect, r;
1962 IDirectDraw *ddraw;
1963 HWND window;
1964 HRESULT hr;
1965 ULONG ref;
1967 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1968 0, 0, 100, 100, 0, 0, 0, 0);
1969 ddraw = create_ddraw();
1970 ok(!!ddraw, "Failed to create a ddraw object.\n");
1972 style = GetWindowLongA(window, GWL_STYLE);
1973 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
1974 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
1976 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1977 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1979 tmp = GetWindowLongA(window, GWL_STYLE);
1980 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
1981 tmp = GetWindowLongA(window, GWL_EXSTYLE);
1982 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
1984 GetWindowRect(window, &r);
1985 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
1986 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
1987 r.left, r.top, r.right, r.bottom);
1988 GetClientRect(window, &r);
1989 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
1991 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1992 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1994 tmp = GetWindowLongA(window, GWL_STYLE);
1995 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
1996 tmp = GetWindowLongA(window, GWL_EXSTYLE);
1997 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
1999 ref = IDirectDraw_Release(ddraw);
2000 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2002 DestroyWindow(window);
2005 static void test_redundant_mode_set(void)
2007 DDSURFACEDESC surface_desc = {0};
2008 IDirectDraw *ddraw;
2009 HWND window;
2010 HRESULT hr;
2011 RECT r, s;
2012 ULONG ref;
2014 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2015 0, 0, 100, 100, 0, 0, 0, 0);
2016 ddraw = create_ddraw();
2017 ok(!!ddraw, "Failed to create a ddraw object.\n");
2019 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2020 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2022 surface_desc.dwSize = sizeof(surface_desc);
2023 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
2024 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
2026 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2027 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
2028 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2030 GetWindowRect(window, &r);
2031 r.right /= 2;
2032 r.bottom /= 2;
2033 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2034 GetWindowRect(window, &s);
2035 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2036 r.left, r.top, r.right, r.bottom,
2037 s.left, s.top, s.right, s.bottom);
2039 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2040 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
2041 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2043 GetWindowRect(window, &s);
2044 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2045 r.left, r.top, r.right, r.bottom,
2046 s.left, s.top, s.right, s.bottom);
2048 ref = IDirectDraw_Release(ddraw);
2049 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2051 DestroyWindow(window);
2054 static SIZE screen_size;
2056 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2058 if (message == WM_SIZE)
2060 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2061 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2064 return test_proc(hwnd, message, wparam, lparam);
2067 static void test_coop_level_mode_set(void)
2069 IDirectDrawSurface *primary;
2070 RECT fullscreen_rect, r, s;
2071 IDirectDraw *ddraw;
2072 DDSURFACEDESC ddsd;
2073 WNDCLASSA wc = {0};
2074 HWND window;
2075 HRESULT hr;
2076 ULONG ref;
2078 static const UINT exclusive_messages[] =
2080 WM_WINDOWPOSCHANGING,
2081 WM_WINDOWPOSCHANGED,
2082 WM_SIZE,
2083 WM_DISPLAYCHANGE,
2087 static const UINT normal_messages[] =
2089 WM_DISPLAYCHANGE,
2093 ddraw = create_ddraw();
2094 ok(!!ddraw, "Failed to create a ddraw object.\n");
2096 wc.lpfnWndProc = mode_set_proc;
2097 wc.lpszClassName = "ddraw_test_wndproc_wc";
2098 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2100 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2101 0, 0, 100, 100, 0, 0, 0, 0);
2103 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2104 SetRect(&s, 0, 0, 640, 480);
2106 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2107 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2109 GetWindowRect(window, &r);
2110 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2111 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2112 r.left, r.top, r.right, r.bottom);
2114 memset(&ddsd, 0, sizeof(ddsd));
2115 ddsd.dwSize = sizeof(ddsd);
2116 ddsd.dwFlags = DDSD_CAPS;
2117 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2119 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2120 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2121 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2122 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2123 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2124 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2125 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2126 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2128 GetWindowRect(window, &r);
2129 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2130 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2131 r.left, r.top, r.right, r.bottom);
2133 expect_messages = exclusive_messages;
2134 screen_size.cx = 0;
2135 screen_size.cy = 0;
2137 hr = set_display_mode(ddraw, 640, 480);
2138 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2140 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2141 expect_messages = NULL;
2142 ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
2143 "Expected screen size %ux%u, got %ux%u.\n",
2144 s.right, s.bottom, screen_size.cx, screen_size.cy);
2146 GetWindowRect(window, &r);
2147 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2148 s.left, s.top, s.right, s.bottom,
2149 r.left, r.top, r.right, r.bottom);
2151 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2152 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2153 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2154 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2155 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2156 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2157 IDirectDrawSurface_Release(primary);
2159 memset(&ddsd, 0, sizeof(ddsd));
2160 ddsd.dwSize = sizeof(ddsd);
2161 ddsd.dwFlags = DDSD_CAPS;
2162 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2164 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2165 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2166 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2167 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2168 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2169 s.right - s.left, ddsd.dwWidth);
2170 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2171 s.bottom - s.top, ddsd.dwHeight);
2173 GetWindowRect(window, &r);
2174 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2175 s.left, s.top, s.right, s.bottom,
2176 r.left, r.top, r.right, r.bottom);
2178 expect_messages = exclusive_messages;
2179 screen_size.cx = 0;
2180 screen_size.cy = 0;
2182 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2183 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2185 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2186 expect_messages = NULL;
2187 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2188 "Expected screen size %ux%u, got %ux%u.\n",
2189 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2191 GetWindowRect(window, &r);
2192 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2193 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2194 r.left, r.top, r.right, r.bottom);
2196 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2197 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2198 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2199 s.right - s.left, ddsd.dwWidth);
2200 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2201 s.bottom - s.top, ddsd.dwHeight);
2202 IDirectDrawSurface_Release(primary);
2204 memset(&ddsd, 0, sizeof(ddsd));
2205 ddsd.dwSize = sizeof(ddsd);
2206 ddsd.dwFlags = DDSD_CAPS;
2207 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2209 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2210 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2211 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2212 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2213 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2214 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2215 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2216 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2218 GetWindowRect(window, &r);
2219 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2220 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2221 r.left, r.top, r.right, r.bottom);
2223 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2224 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2226 GetWindowRect(window, &r);
2227 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2228 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2229 r.left, r.top, r.right, r.bottom);
2231 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2232 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2233 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2234 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2235 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2236 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2237 IDirectDrawSurface_Release(primary);
2239 memset(&ddsd, 0, sizeof(ddsd));
2240 ddsd.dwSize = sizeof(ddsd);
2241 ddsd.dwFlags = DDSD_CAPS;
2242 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2244 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2245 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2246 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2247 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2248 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2249 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2250 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2251 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2253 GetWindowRect(window, &r);
2254 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2255 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2256 r.left, r.top, r.right, r.bottom);
2258 expect_messages = normal_messages;
2259 screen_size.cx = 0;
2260 screen_size.cy = 0;
2262 hr = set_display_mode(ddraw, 640, 480);
2263 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
2265 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
2266 IDirectDrawSurface_Release(primary);
2267 IDirectDraw_Release(ddraw);
2268 goto done;
2270 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2272 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2273 expect_messages = NULL;
2274 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2276 GetWindowRect(window, &r);
2277 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2278 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2279 r.left, r.top, r.right, r.bottom);
2281 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2282 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2283 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2284 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2285 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2286 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2287 IDirectDrawSurface_Release(primary);
2289 memset(&ddsd, 0, sizeof(ddsd));
2290 ddsd.dwSize = sizeof(ddsd);
2291 ddsd.dwFlags = DDSD_CAPS;
2292 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2294 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2295 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2296 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2297 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2298 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2299 s.right - s.left, ddsd.dwWidth);
2300 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2301 s.bottom - s.top, ddsd.dwHeight);
2303 GetWindowRect(window, &r);
2304 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2305 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2306 r.left, r.top, r.right, r.bottom);
2308 expect_messages = normal_messages;
2309 screen_size.cx = 0;
2310 screen_size.cy = 0;
2312 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2313 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2315 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2316 expect_messages = NULL;
2317 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2319 GetWindowRect(window, &r);
2320 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2321 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2322 r.left, r.top, r.right, r.bottom);
2324 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2325 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2326 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2327 s.right - s.left, ddsd.dwWidth);
2328 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2329 s.bottom - s.top, ddsd.dwHeight);
2330 IDirectDrawSurface_Release(primary);
2332 memset(&ddsd, 0, sizeof(ddsd));
2333 ddsd.dwSize = sizeof(ddsd);
2334 ddsd.dwFlags = DDSD_CAPS;
2335 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2337 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2338 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2339 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2340 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2341 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2342 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2343 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2344 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2346 GetWindowRect(window, &r);
2347 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2348 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2349 r.left, r.top, r.right, r.bottom);
2351 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2352 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2353 * not DDSCL_FULLSCREEN. */
2354 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2355 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2357 GetWindowRect(window, &r);
2358 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2359 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2360 r.left, r.top, r.right, r.bottom);
2362 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2363 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2364 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2365 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2366 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2367 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2368 IDirectDrawSurface_Release(primary);
2370 memset(&ddsd, 0, sizeof(ddsd));
2371 ddsd.dwSize = sizeof(ddsd);
2372 ddsd.dwFlags = DDSD_CAPS;
2373 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2375 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2376 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2377 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2378 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2379 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2380 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2381 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2382 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2384 GetWindowRect(window, &r);
2385 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2386 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2387 r.left, r.top, r.right, r.bottom);
2389 expect_messages = normal_messages;
2390 screen_size.cx = 0;
2391 screen_size.cy = 0;
2393 hr = set_display_mode(ddraw, 640, 480);
2394 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2396 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2397 expect_messages = NULL;
2398 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2400 GetWindowRect(window, &r);
2401 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2402 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2403 r.left, r.top, r.right, r.bottom);
2405 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2406 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2407 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2408 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2409 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2410 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2411 IDirectDrawSurface_Release(primary);
2413 memset(&ddsd, 0, sizeof(ddsd));
2414 ddsd.dwSize = sizeof(ddsd);
2415 ddsd.dwFlags = DDSD_CAPS;
2416 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2418 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2419 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2420 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2421 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2422 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2423 s.right - s.left, ddsd.dwWidth);
2424 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2425 s.bottom - s.top, ddsd.dwHeight);
2427 GetWindowRect(window, &r);
2428 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2429 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2430 r.left, r.top, r.right, r.bottom);
2432 expect_messages = normal_messages;
2433 screen_size.cx = 0;
2434 screen_size.cy = 0;
2436 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2437 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2439 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2440 expect_messages = NULL;
2441 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", 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 = IDirectDrawSurface_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 IDirectDrawSurface_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 = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2462 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2463 hr = IDirectDrawSurface_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);
2469 IDirectDrawSurface_Release(primary);
2471 GetWindowRect(window, &r);
2472 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2473 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2474 r.left, r.top, r.right, r.bottom);
2476 /* Unlike ddraw2-7, changing from EXCLUSIVE to NORMAL does not restore the resolution */
2477 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2478 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2479 hr = set_display_mode(ddraw, 640, 480);
2480 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2482 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2483 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2485 memset(&ddsd, 0, sizeof(ddsd));
2486 ddsd.dwSize = sizeof(ddsd);
2487 ddsd.dwFlags = DDSD_CAPS;
2488 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2490 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2491 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2492 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2493 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2494 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2495 s.right - s.left, ddsd.dwWidth);
2496 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2497 s.bottom - s.top, ddsd.dwHeight);
2498 IDirectDrawSurface_Release(primary);
2499 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2500 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2502 ref = IDirectDraw_Release(ddraw);
2503 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2505 GetWindowRect(window, &r);
2506 ok(EqualRect(&r, &s), "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 done:
2511 expect_messages = NULL;
2512 DestroyWindow(window);
2513 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2516 static void test_coop_level_mode_set_multi(void)
2518 IDirectDraw *ddraw1, *ddraw2;
2519 UINT orig_w, orig_h, w, h;
2520 HWND window;
2521 HRESULT hr;
2522 ULONG ref;
2524 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2525 0, 0, 100, 100, 0, 0, 0, 0);
2526 ddraw1 = create_ddraw();
2527 ok(!!ddraw1, "Failed to create a ddraw object.\n");
2529 orig_w = GetSystemMetrics(SM_CXSCREEN);
2530 orig_h = GetSystemMetrics(SM_CYSCREEN);
2532 /* With just a single ddraw object, the display mode is restored on
2533 * release. */
2534 hr = set_display_mode(ddraw1, 800, 600);
2535 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
2537 win_skip("Broken SetDisplayMode(), skipping test.\n");
2538 IDirectDraw_Release(ddraw1);
2539 DestroyWindow(window);
2540 return;
2542 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2543 w = GetSystemMetrics(SM_CXSCREEN);
2544 ok(w == 800, "Got unexpected screen width %u.\n", w);
2545 h = GetSystemMetrics(SM_CYSCREEN);
2546 ok(h == 600, "Got unexpected screen height %u.\n", h);
2548 ref = IDirectDraw_Release(ddraw1);
2549 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2550 w = GetSystemMetrics(SM_CXSCREEN);
2551 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2552 h = GetSystemMetrics(SM_CYSCREEN);
2553 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2555 /* When there are multiple ddraw objects, the display mode is restored to
2556 * the initial mode, before the first SetDisplayMode() call. */
2557 ddraw1 = create_ddraw();
2558 hr = set_display_mode(ddraw1, 800, 600);
2559 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2560 w = GetSystemMetrics(SM_CXSCREEN);
2561 ok(w == 800, "Got unexpected screen width %u.\n", w);
2562 h = GetSystemMetrics(SM_CYSCREEN);
2563 ok(h == 600, "Got unexpected screen height %u.\n", h);
2565 ddraw2 = create_ddraw();
2566 hr = set_display_mode(ddraw2, 640, 480);
2567 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2568 w = GetSystemMetrics(SM_CXSCREEN);
2569 ok(w == 640, "Got unexpected screen width %u.\n", w);
2570 h = GetSystemMetrics(SM_CYSCREEN);
2571 ok(h == 480, "Got unexpected screen height %u.\n", h);
2573 ref = IDirectDraw_Release(ddraw2);
2574 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2575 w = GetSystemMetrics(SM_CXSCREEN);
2576 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2577 h = GetSystemMetrics(SM_CYSCREEN);
2578 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2580 ref = IDirectDraw_Release(ddraw1);
2581 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2582 w = GetSystemMetrics(SM_CXSCREEN);
2583 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2584 h = GetSystemMetrics(SM_CYSCREEN);
2585 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2587 /* Regardless of release ordering. */
2588 ddraw1 = create_ddraw();
2589 hr = set_display_mode(ddraw1, 800, 600);
2590 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2591 w = GetSystemMetrics(SM_CXSCREEN);
2592 ok(w == 800, "Got unexpected screen width %u.\n", w);
2593 h = GetSystemMetrics(SM_CYSCREEN);
2594 ok(h == 600, "Got unexpected screen height %u.\n", h);
2596 ddraw2 = create_ddraw();
2597 hr = set_display_mode(ddraw2, 640, 480);
2598 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2599 w = GetSystemMetrics(SM_CXSCREEN);
2600 ok(w == 640, "Got unexpected screen width %u.\n", w);
2601 h = GetSystemMetrics(SM_CYSCREEN);
2602 ok(h == 480, "Got unexpected screen height %u.\n", h);
2604 ref = IDirectDraw_Release(ddraw1);
2605 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2606 w = GetSystemMetrics(SM_CXSCREEN);
2607 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2608 h = GetSystemMetrics(SM_CYSCREEN);
2609 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2611 ref = IDirectDraw_Release(ddraw2);
2612 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2613 w = GetSystemMetrics(SM_CXSCREEN);
2614 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2615 h = GetSystemMetrics(SM_CYSCREEN);
2616 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2618 /* But only for ddraw objects that called SetDisplayMode(). */
2619 ddraw1 = create_ddraw();
2620 ddraw2 = create_ddraw();
2621 hr = set_display_mode(ddraw2, 640, 480);
2622 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2623 w = GetSystemMetrics(SM_CXSCREEN);
2624 ok(w == 640, "Got unexpected screen width %u.\n", w);
2625 h = GetSystemMetrics(SM_CYSCREEN);
2626 ok(h == 480, "Got unexpected screen height %u.\n", h);
2628 ref = IDirectDraw_Release(ddraw1);
2629 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2630 w = GetSystemMetrics(SM_CXSCREEN);
2631 ok(w == 640, "Got unexpected screen width %u.\n", w);
2632 h = GetSystemMetrics(SM_CYSCREEN);
2633 ok(h == 480, "Got unexpected screen height %u.\n", h);
2635 ref = IDirectDraw_Release(ddraw2);
2636 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2637 w = GetSystemMetrics(SM_CXSCREEN);
2638 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2639 h = GetSystemMetrics(SM_CYSCREEN);
2640 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2642 /* If there's a ddraw object that's currently in exclusive mode, it blocks
2643 * restoring the display mode. */
2644 ddraw1 = create_ddraw();
2645 hr = set_display_mode(ddraw1, 800, 600);
2646 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2647 w = GetSystemMetrics(SM_CXSCREEN);
2648 ok(w == 800, "Got unexpected screen width %u.\n", w);
2649 h = GetSystemMetrics(SM_CYSCREEN);
2650 ok(h == 600, "Got unexpected screen height %u.\n", h);
2652 ddraw2 = create_ddraw();
2653 hr = set_display_mode(ddraw2, 640, 480);
2654 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2655 w = GetSystemMetrics(SM_CXSCREEN);
2656 ok(w == 640, "Got unexpected screen width %u.\n", w);
2657 h = GetSystemMetrics(SM_CYSCREEN);
2658 ok(h == 480, "Got unexpected screen height %u.\n", h);
2660 hr = IDirectDraw_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2661 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2663 ref = IDirectDraw_Release(ddraw1);
2664 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2665 w = GetSystemMetrics(SM_CXSCREEN);
2666 ok(w == 640, "Got unexpected screen width %u.\n", w);
2667 h = GetSystemMetrics(SM_CYSCREEN);
2668 ok(h == 480, "Got unexpected screen height %u.\n", h);
2670 ref = IDirectDraw_Release(ddraw2);
2671 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2672 w = GetSystemMetrics(SM_CXSCREEN);
2673 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2674 h = GetSystemMetrics(SM_CYSCREEN);
2675 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2677 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
2678 ddraw1 = create_ddraw();
2679 hr = set_display_mode(ddraw1, 800, 600);
2680 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2681 w = GetSystemMetrics(SM_CXSCREEN);
2682 ok(w == 800, "Got unexpected screen width %u.\n", w);
2683 h = GetSystemMetrics(SM_CYSCREEN);
2684 ok(h == 600, "Got unexpected screen height %u.\n", h);
2686 hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2687 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2689 ddraw2 = create_ddraw();
2690 hr = set_display_mode(ddraw2, 640, 480);
2691 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
2693 ref = IDirectDraw_Release(ddraw1);
2694 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2695 w = GetSystemMetrics(SM_CXSCREEN);
2696 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2697 h = GetSystemMetrics(SM_CYSCREEN);
2698 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2700 ref = IDirectDraw_Release(ddraw2);
2701 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2702 w = GetSystemMetrics(SM_CXSCREEN);
2703 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2704 h = GetSystemMetrics(SM_CYSCREEN);
2705 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2707 DestroyWindow(window);
2710 static void test_initialize(void)
2712 IDirectDraw *ddraw;
2713 IDirect3D *d3d;
2714 HRESULT hr;
2716 ddraw = create_ddraw();
2717 ok(!!ddraw, "Failed to create a ddraw object.\n");
2719 hr = IDirectDraw_Initialize(ddraw, NULL);
2720 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
2721 IDirectDraw_Release(ddraw);
2723 CoInitialize(NULL);
2724 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw);
2725 ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
2726 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
2727 if (SUCCEEDED(hr))
2729 /* IDirect3D_Initialize() just returns DDERR_ALREADYINITIALIZED. */
2730 hr = IDirect3D_Initialize(d3d, NULL);
2731 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2732 IDirect3D_Release(d3d);
2734 else
2735 skip("D3D interface is not available, skipping test.\n");
2736 hr = IDirectDraw_Initialize(ddraw, NULL);
2737 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
2738 hr = IDirectDraw_Initialize(ddraw, NULL);
2739 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2740 IDirectDraw_Release(ddraw);
2741 CoUninitialize();
2743 if (0) /* This crashes on the W2KPROSP4 testbot. */
2745 CoInitialize(NULL);
2746 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d);
2747 ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#x, expected E_NOINTERFACE.\n", hr);
2748 CoUninitialize();
2752 static void test_coop_level_surf_create(void)
2754 IDirectDrawSurface *surface;
2755 IDirectDraw *ddraw;
2756 DDSURFACEDESC ddsd;
2757 HRESULT hr;
2759 ddraw = create_ddraw();
2760 ok(!!ddraw, "Failed to create a ddraw object.\n");
2762 memset(&ddsd, 0, sizeof(ddsd));
2763 ddsd.dwSize = sizeof(ddsd);
2764 ddsd.dwFlags = DDSD_CAPS;
2765 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2766 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
2767 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
2769 IDirectDraw_Release(ddraw);
2772 static void test_coop_level_multi_window(void)
2774 HWND window1, window2;
2775 IDirectDraw *ddraw;
2776 HRESULT hr;
2778 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
2779 0, 0, 640, 480, 0, 0, 0, 0);
2780 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
2781 0, 0, 640, 480, 0, 0, 0, 0);
2782 ddraw = create_ddraw();
2783 ok(!!ddraw, "Failed to create a ddraw object.\n");
2785 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
2786 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2787 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
2788 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2789 ok(IsWindow(window1), "Window 1 was destroyed.\n");
2790 ok(IsWindow(window2), "Window 2 was destroyed.\n");
2792 IDirectDraw_Release(ddraw);
2793 DestroyWindow(window2);
2794 DestroyWindow(window1);
2797 static void test_clear_rect_count(void)
2799 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
2800 IDirect3DMaterial *white, *red, *green, *blue;
2801 IDirect3DViewport *viewport;
2802 IDirect3DDevice *device;
2803 IDirectDrawSurface *rt;
2804 IDirectDraw *ddraw;
2805 D3DCOLOR color;
2806 HWND window;
2807 HRESULT hr;
2809 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2810 0, 0, 640, 480, 0, 0, 0, 0);
2811 ddraw = create_ddraw();
2812 ok(!!ddraw, "Failed to create a ddraw object.\n");
2813 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2815 skip("Failed to create a 3D device, skipping test.\n");
2816 IDirectDraw_Release(ddraw);
2817 DestroyWindow(window);
2818 return;
2821 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
2822 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
2824 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
2825 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
2826 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
2827 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
2828 viewport = create_viewport(device, 0, 0, 640, 480);
2830 viewport_set_background(device, viewport, white);
2831 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2832 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2833 viewport_set_background(device, viewport, red);
2834 hr = IDirect3DViewport_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
2835 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2836 viewport_set_background(device, viewport, green);
2837 hr = IDirect3DViewport_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
2838 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2839 viewport_set_background(device, viewport, blue);
2840 hr = IDirect3DViewport_Clear(viewport, 1, NULL, D3DCLEAR_TARGET);
2841 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2843 color = get_surface_color(rt, 320, 240);
2844 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
2846 IDirectDrawSurface_Release(rt);
2847 destroy_viewport(device, viewport);
2848 destroy_material(white);
2849 destroy_material(red);
2850 destroy_material(green);
2851 destroy_material(blue);
2852 IDirect3DDevice_Release(device);
2853 IDirectDraw_Release(ddraw);
2854 DestroyWindow(window);
2857 static struct
2859 BOOL received;
2860 IDirectDraw *ddraw;
2861 HWND window;
2862 DWORD coop_level;
2863 } activateapp_testdata;
2865 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2867 if (message == WM_ACTIVATEAPP)
2869 if (activateapp_testdata.ddraw)
2871 HRESULT hr;
2872 activateapp_testdata.received = FALSE;
2873 hr = IDirectDraw_SetCooperativeLevel(activateapp_testdata.ddraw,
2874 activateapp_testdata.window, activateapp_testdata.coop_level);
2875 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
2876 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
2878 activateapp_testdata.received = TRUE;
2881 return DefWindowProcA(hwnd, message, wparam, lparam);
2884 static void test_coop_level_activateapp(void)
2886 IDirectDraw *ddraw;
2887 HRESULT hr;
2888 HWND window;
2889 WNDCLASSA wc = {0};
2890 DDSURFACEDESC ddsd;
2891 IDirectDrawSurface *surface;
2893 ddraw = create_ddraw();
2894 ok(!!ddraw, "Failed to create a ddraw object.\n");
2896 wc.lpfnWndProc = activateapp_test_proc;
2897 wc.lpszClassName = "ddraw_test_wndproc_wc";
2898 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2900 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2901 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2903 /* Exclusive with window already active. */
2904 SetActiveWindow(window);
2905 activateapp_testdata.received = FALSE;
2906 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2907 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2908 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
2909 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2910 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2912 /* Exclusive with window not active. */
2913 SetActiveWindow(NULL);
2914 activateapp_testdata.received = FALSE;
2915 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2916 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2917 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
2918 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2919 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2921 /* Normal with window not active, then exclusive with the same window. */
2922 SetActiveWindow(NULL);
2923 activateapp_testdata.received = FALSE;
2924 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2925 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2926 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
2927 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2928 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2929 /* Except in the first SetCooperativeLevel call, Windows XP randomly does not send
2930 * WM_ACTIVATEAPP. Windows 7 sends the message reliably. Mark the XP behavior broken. */
2931 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
2932 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
2933 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2934 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2936 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
2937 SetActiveWindow(NULL);
2938 activateapp_testdata.received = FALSE;
2939 activateapp_testdata.ddraw = ddraw;
2940 activateapp_testdata.window = window;
2941 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
2942 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2943 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2944 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
2945 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
2946 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2947 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2949 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
2950 * succeeding. Another switch to exclusive and back to normal is needed to release the
2951 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
2952 * WM_ACTIVATEAPP messages. */
2953 activateapp_testdata.ddraw = NULL;
2954 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2955 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2956 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2957 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2959 /* Setting DDSCL_NORMAL with recursive invocation. */
2960 SetActiveWindow(NULL);
2961 activateapp_testdata.received = FALSE;
2962 activateapp_testdata.ddraw = ddraw;
2963 activateapp_testdata.window = window;
2964 activateapp_testdata.coop_level = DDSCL_NORMAL;
2965 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2966 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2967 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
2968 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
2970 /* DDraw is in exlusive mode now. */
2971 memset(&ddsd, 0, sizeof(ddsd));
2972 ddsd.dwSize = sizeof(ddsd);
2973 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
2974 ddsd.dwBackBufferCount = 1;
2975 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
2976 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
2977 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2978 IDirectDrawSurface_Release(surface);
2980 /* Recover again, just to be sure. */
2981 activateapp_testdata.ddraw = NULL;
2982 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2983 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2984 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2985 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2987 DestroyWindow(window);
2988 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2989 IDirectDraw_Release(ddraw);
2992 struct format_support_check
2994 const DDPIXELFORMAT *format;
2995 BOOL supported;
2998 static HRESULT WINAPI test_unsupported_formats_cb(DDSURFACEDESC *desc, void *ctx)
3000 struct format_support_check *format = ctx;
3002 if (!memcmp(format->format, &desc->ddpfPixelFormat, sizeof(*format->format)))
3004 format->supported = TRUE;
3005 return DDENUMRET_CANCEL;
3008 return DDENUMRET_OK;
3011 static void test_unsupported_formats(void)
3013 HRESULT hr;
3014 BOOL expect_success;
3015 HWND window;
3016 IDirectDraw *ddraw;
3017 IDirect3DDevice *device;
3018 IDirectDrawSurface *surface;
3019 DDSURFACEDESC ddsd;
3020 unsigned int i, j;
3021 DWORD expected_caps;
3022 static const struct
3024 const char *name;
3025 DDPIXELFORMAT fmt;
3027 formats[] =
3030 "D3DFMT_A8R8G8B8",
3032 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3033 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
3037 "D3DFMT_P8",
3039 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3040 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3044 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
3046 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3047 0, 0, 640, 480, 0, 0, 0, 0);
3048 ddraw = create_ddraw();
3049 ok(!!ddraw, "Failed to create a ddraw object.\n");
3050 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3052 skip("Failed to create a 3D device, skipping test.\n");
3053 IDirectDraw_Release(ddraw);
3054 DestroyWindow(window);
3055 return;
3058 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
3060 struct format_support_check check = {&formats[i].fmt, FALSE};
3061 hr = IDirect3DDevice_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
3062 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
3064 for (j = 0; j < sizeof(caps) / sizeof(*caps); j++)
3066 memset(&ddsd, 0, sizeof(ddsd));
3067 ddsd.dwSize = sizeof(ddsd);
3068 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3069 ddsd.ddpfPixelFormat = formats[i].fmt;
3070 ddsd.dwWidth = 4;
3071 ddsd.dwHeight = 4;
3072 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
3074 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
3075 expect_success = FALSE;
3076 else
3077 expect_success = TRUE;
3079 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3080 ok(SUCCEEDED(hr) == expect_success,
3081 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
3082 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
3083 if (FAILED(hr))
3084 continue;
3086 memset(&ddsd, 0, sizeof(ddsd));
3087 ddsd.dwSize = sizeof(ddsd);
3088 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
3089 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3091 if (caps[j] & DDSCAPS_VIDEOMEMORY)
3092 expected_caps = DDSCAPS_VIDEOMEMORY;
3093 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
3094 expected_caps = DDSCAPS_SYSTEMMEMORY;
3095 else if (check.supported)
3096 expected_caps = DDSCAPS_VIDEOMEMORY;
3097 else
3098 expected_caps = DDSCAPS_SYSTEMMEMORY;
3100 ok(ddsd.ddsCaps.dwCaps & expected_caps,
3101 "Expected capability %#x, format %s, input cap %#x.\n",
3102 expected_caps, formats[i].name, caps[j]);
3104 IDirectDrawSurface_Release(surface);
3108 IDirect3DDevice_Release(device);
3109 IDirectDraw_Release(ddraw);
3110 DestroyWindow(window);
3113 static void test_rt_caps(void)
3115 PALETTEENTRY palette_entries[256];
3116 IDirectDrawPalette *palette;
3117 IDirect3DDevice *device;
3118 IDirectDraw *ddraw;
3119 DWORD z_depth = 0;
3120 unsigned int i;
3121 ULONG refcount;
3122 HWND window;
3123 HRESULT hr;
3125 static const DDPIXELFORMAT p8_fmt =
3127 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3128 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
3131 static const struct
3133 const DDPIXELFORMAT *pf;
3134 DWORD caps_in;
3135 DWORD caps_out;
3136 HRESULT create_device_hr;
3137 BOOL create_may_fail;
3139 test_data[] =
3142 NULL,
3143 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3144 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3145 D3D_OK,
3146 FALSE,
3149 NULL,
3150 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3151 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3152 D3D_OK,
3153 FALSE,
3156 NULL,
3157 DDSCAPS_OFFSCREENPLAIN,
3158 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3159 DDERR_INVALIDCAPS,
3160 FALSE,
3163 NULL,
3164 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3165 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3166 D3DERR_SURFACENOTINVIDMEM,
3167 FALSE,
3170 NULL,
3171 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3172 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3173 DDERR_INVALIDCAPS,
3174 FALSE,
3177 NULL,
3178 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3179 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3180 D3D_OK,
3181 FALSE,
3184 NULL,
3185 DDSCAPS_3DDEVICE,
3186 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3187 D3D_OK,
3188 FALSE,
3191 NULL,
3193 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3194 DDERR_INVALIDCAPS,
3195 FALSE,
3198 NULL,
3199 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3200 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3201 D3DERR_SURFACENOTINVIDMEM,
3202 FALSE,
3205 NULL,
3206 DDSCAPS_SYSTEMMEMORY,
3207 DDSCAPS_SYSTEMMEMORY,
3208 DDERR_INVALIDCAPS,
3209 FALSE,
3212 &p8_fmt,
3214 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3215 DDERR_INVALIDCAPS,
3216 FALSE,
3219 &p8_fmt,
3220 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3221 ~0U /* AMD r200 */ ,
3222 DDERR_NOPALETTEATTACHED,
3223 FALSE,
3226 &p8_fmt,
3227 DDSCAPS_OFFSCREENPLAIN,
3228 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3229 DDERR_INVALIDCAPS,
3230 FALSE,
3233 &p8_fmt,
3234 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3235 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3236 DDERR_NOPALETTEATTACHED,
3237 FALSE,
3240 &p8_fmt,
3241 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3242 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3243 DDERR_INVALIDCAPS,
3244 FALSE,
3247 NULL,
3248 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
3249 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
3250 DDERR_INVALIDCAPS,
3251 TRUE /* AMD Evergreen */,
3254 NULL,
3255 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3256 ~0U /* AMD Evergreen */,
3257 DDERR_INVALIDCAPS,
3258 FALSE,
3261 NULL,
3262 DDSCAPS_ZBUFFER,
3263 ~0U /* AMD Evergreen */,
3264 DDERR_INVALIDCAPS,
3265 FALSE,
3268 NULL,
3269 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3270 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3271 DDERR_INVALIDCAPS,
3272 TRUE /* Nvidia Kepler */,
3275 NULL,
3276 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3277 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3278 DDERR_INVALIDCAPS,
3279 TRUE /* Nvidia Kepler */,
3283 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3284 0, 0, 640, 480, 0, 0, 0, 0);
3285 ddraw = create_ddraw();
3286 ok(!!ddraw, "Failed to create a ddraw object.\n");
3287 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3289 skip("Failed to create a 3D device, skipping test.\n");
3290 IDirectDraw_Release(ddraw);
3291 DestroyWindow(window);
3292 return;
3294 z_depth = get_device_z_depth(device);
3295 ok(!!z_depth, "Failed to get device z depth.\n");
3296 IDirect3DDevice_Release(device);
3298 memset(palette_entries, 0, sizeof(palette_entries));
3299 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
3300 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
3302 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
3304 IDirectDrawSurface *surface;
3305 DDSURFACEDESC surface_desc;
3306 IDirect3DDevice *device;
3308 memset(&surface_desc, 0, sizeof(surface_desc));
3309 surface_desc.dwSize = sizeof(surface_desc);
3310 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3311 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
3312 if (test_data[i].pf)
3314 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
3315 surface_desc.ddpfPixelFormat = *test_data[i].pf;
3317 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
3319 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
3320 U2(surface_desc).dwZBufferBitDepth = z_depth;
3322 surface_desc.dwWidth = 640;
3323 surface_desc.dwHeight = 480;
3324 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3325 ok(SUCCEEDED(hr) || broken(test_data[i].create_may_fail),
3326 "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
3327 i, test_data[i].caps_in, hr);
3328 if (FAILED(hr))
3329 continue;
3331 memset(&surface_desc, 0, sizeof(surface_desc));
3332 surface_desc.dwSize = sizeof(surface_desc);
3333 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
3334 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
3335 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
3336 "Test %u: Got unexpected caps %#x, expected %#x.\n",
3337 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
3339 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
3340 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
3341 i, hr, test_data[i].create_device_hr);
3342 if (hr == DDERR_NOPALETTEATTACHED)
3344 hr = IDirectDrawSurface_SetPalette(surface, palette);
3345 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
3346 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
3347 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
3348 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
3349 else
3350 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
3352 if (SUCCEEDED(hr))
3354 refcount = IDirect3DDevice_Release(device);
3355 ok(refcount == 1, "Test %u: Got unexpected refcount %u.\n", i, refcount);
3358 refcount = IDirectDrawSurface_Release(surface);
3359 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
3362 IDirectDrawPalette_Release(palette);
3363 refcount = IDirectDraw_Release(ddraw);
3364 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3365 DestroyWindow(window);
3368 static void test_primary_caps(void)
3370 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
3371 IDirectDrawSurface *surface;
3372 DDSURFACEDESC surface_desc;
3373 IDirectDraw *ddraw;
3374 unsigned int i;
3375 ULONG refcount;
3376 HWND window;
3377 HRESULT hr;
3379 static const struct
3381 DWORD coop_level;
3382 DWORD caps_in;
3383 DWORD back_buffer_count;
3384 HRESULT hr;
3385 DWORD caps_out;
3387 test_data[] =
3390 DDSCL_NORMAL,
3391 DDSCAPS_PRIMARYSURFACE,
3392 ~0u,
3393 DD_OK,
3394 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
3397 DDSCL_NORMAL,
3398 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
3399 ~0u,
3400 DDERR_INVALIDCAPS,
3401 ~0u,
3404 DDSCL_NORMAL,
3405 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
3406 ~0u,
3407 DD_OK,
3408 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
3411 DDSCL_NORMAL,
3412 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
3413 ~0u,
3414 DDERR_INVALIDCAPS,
3415 ~0u,
3418 DDSCL_NORMAL,
3419 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
3420 ~0u,
3421 DDERR_INVALIDCAPS,
3422 ~0u,
3425 DDSCL_NORMAL,
3426 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
3427 ~0u,
3428 DDERR_INVALIDCAPS,
3429 ~0u,
3432 DDSCL_NORMAL,
3433 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3434 ~0u,
3435 DDERR_INVALIDCAPS,
3436 ~0u,
3439 DDSCL_NORMAL,
3440 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3442 DDERR_INVALIDCAPS,
3443 ~0u,
3446 DDSCL_NORMAL,
3447 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3449 DDERR_NOEXCLUSIVEMODE,
3450 ~0u,
3453 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3454 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3456 DDERR_INVALIDCAPS,
3457 ~0u,
3460 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3461 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3463 DD_OK,
3464 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
3467 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3468 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
3470 DDERR_INVALIDCAPS,
3471 ~0u,
3474 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3475 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
3477 DDERR_INVALIDCAPS,
3478 ~0u,
3482 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3483 0, 0, 640, 480, 0, 0, 0, 0);
3484 ddraw = create_ddraw();
3485 ok(!!ddraw, "Failed to create a ddraw object.\n");
3487 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
3489 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
3490 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3492 memset(&surface_desc, 0, sizeof(surface_desc));
3493 surface_desc.dwSize = sizeof(surface_desc);
3494 surface_desc.dwFlags = DDSD_CAPS;
3495 if (test_data[i].back_buffer_count != ~0u)
3496 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
3497 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
3498 surface_desc.dwBackBufferCount = test_data[i].back_buffer_count;
3499 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3500 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
3501 if (FAILED(hr))
3502 continue;
3504 memset(&surface_desc, 0, sizeof(surface_desc));
3505 surface_desc.dwSize = sizeof(surface_desc);
3506 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
3507 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
3508 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
3509 "Test %u: Got unexpected caps %#x, expected %#x.\n",
3510 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
3512 IDirectDrawSurface_Release(surface);
3515 refcount = IDirectDraw_Release(ddraw);
3516 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3517 DestroyWindow(window);
3520 static void test_surface_lock(void)
3522 IDirectDraw *ddraw;
3523 IDirectDrawSurface *surface;
3524 IDirect3DDevice *device;
3525 HRESULT hr;
3526 HWND window;
3527 unsigned int i;
3528 DDSURFACEDESC ddsd;
3529 ULONG refcount;
3530 DWORD z_depth = 0;
3531 static const struct
3533 DWORD caps;
3534 const char *name;
3536 tests[] =
3539 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
3540 "videomemory offscreenplain"
3543 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3544 "systemmemory offscreenplain"
3547 DDSCAPS_PRIMARYSURFACE,
3548 "primary"
3551 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
3552 "videomemory texture"
3555 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
3556 "systemmemory texture"
3559 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3560 "render target"
3563 DDSCAPS_ZBUFFER,
3564 "Z buffer"
3568 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3569 0, 0, 640, 480, 0, 0, 0, 0);
3570 ddraw = create_ddraw();
3571 ok(!!ddraw, "Failed to create a ddraw object.\n");
3572 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3574 skip("Failed to create a 3D device, skipping test.\n");
3575 IDirectDraw_Release(ddraw);
3576 DestroyWindow(window);
3577 return;
3579 z_depth = get_device_z_depth(device);
3580 ok(!!z_depth, "Failed to get device z depth.\n");
3581 IDirect3DDevice_Release(device);
3583 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
3585 memset(&ddsd, 0, sizeof(ddsd));
3586 ddsd.dwSize = sizeof(ddsd);
3587 ddsd.dwFlags = DDSD_CAPS;
3588 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
3590 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
3591 ddsd.dwWidth = 64;
3592 ddsd.dwHeight = 64;
3594 if (tests[i].caps & DDSCAPS_ZBUFFER)
3596 ddsd.dwFlags |= DDSD_ZBUFFERBITDEPTH;
3597 U2(ddsd).dwZBufferBitDepth = z_depth;
3599 ddsd.ddsCaps.dwCaps = tests[i].caps;
3601 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3602 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
3604 memset(&ddsd, 0, sizeof(ddsd));
3605 ddsd.dwSize = sizeof(ddsd);
3606 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
3607 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
3608 if (SUCCEEDED(hr))
3610 hr = IDirectDrawSurface_Unlock(surface, NULL);
3611 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
3614 IDirectDrawSurface_Release(surface);
3617 refcount = IDirectDraw_Release(ddraw);
3618 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3619 DestroyWindow(window);
3622 static void test_surface_discard(void)
3624 IDirectDraw *ddraw;
3625 HRESULT hr;
3626 HWND window;
3627 DDSURFACEDESC ddsd;
3628 IDirectDrawSurface *surface, *primary;
3629 void *addr;
3630 static const struct
3632 DWORD caps;
3633 BOOL discard;
3635 tests[] =
3637 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, TRUE},
3638 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, FALSE},
3639 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, TRUE},
3640 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, FALSE},
3642 unsigned int i;
3644 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3645 0, 0, 640, 480, 0, 0, 0, 0);
3646 ddraw = create_ddraw();
3647 ok(!!ddraw, "Failed to create a ddraw object.\n");
3648 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3649 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3651 memset(&ddsd, 0, sizeof(ddsd));
3652 ddsd.dwSize = sizeof(ddsd);
3653 ddsd.dwFlags = DDSD_CAPS;
3654 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3655 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3657 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
3659 BOOL discarded;
3661 memset(&ddsd, 0, sizeof(ddsd));
3662 ddsd.dwSize = sizeof(ddsd);
3663 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3664 ddsd.ddsCaps.dwCaps = tests[i].caps;
3665 ddsd.dwWidth = 64;
3666 ddsd.dwHeight = 64;
3667 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3668 if (FAILED(hr))
3670 skip("Failed to create surface, skipping.\n");
3671 continue;
3674 memset(&ddsd, 0, sizeof(ddsd));
3675 ddsd.dwSize = sizeof(ddsd);
3676 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
3677 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
3678 addr = ddsd.lpSurface;
3679 hr = IDirectDrawSurface_Unlock(surface, NULL);
3680 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
3682 memset(&ddsd, 0, sizeof(ddsd));
3683 ddsd.dwSize = sizeof(ddsd);
3684 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
3685 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
3686 discarded = ddsd.lpSurface != addr;
3687 hr = IDirectDrawSurface_Unlock(surface, NULL);
3688 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
3690 hr = IDirectDrawSurface_Blt(primary, NULL, surface, NULL, DDBLT_WAIT, NULL);
3691 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
3693 memset(&ddsd, 0, sizeof(ddsd));
3694 ddsd.dwSize = sizeof(ddsd);
3695 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
3696 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
3697 discarded |= ddsd.lpSurface != addr;
3698 hr = IDirectDrawSurface_Unlock(surface, NULL);
3699 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
3701 IDirectDrawSurface_Release(surface);
3703 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
3704 * AMD r500, evergreen). Windows XP, at least on AMD r200, never changes the pointer. */
3705 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
3708 IDirectDrawSurface_Release(primary);
3709 IDirectDraw_Release(ddraw);
3710 DestroyWindow(window);
3713 static void test_flip(void)
3715 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
3716 IDirectDrawSurface *primary, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
3717 DDSCAPS caps = {DDSCAPS_FLIP};
3718 DDSURFACEDESC surface_desc;
3719 BOOL sysmem_primary;
3720 IDirectDraw *ddraw;
3721 D3DCOLOR color;
3722 ULONG refcount;
3723 HWND window;
3724 DDBLTFX fx;
3725 HRESULT hr;
3727 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3728 0, 0, 640, 480, 0, 0, 0, 0);
3729 ddraw = create_ddraw();
3730 ok(!!ddraw, "Failed to create a ddraw object.\n");
3732 hr = set_display_mode(ddraw, 640, 480);
3733 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3734 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3735 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3737 memset(&surface_desc, 0, sizeof(surface_desc));
3738 surface_desc.dwSize = sizeof(surface_desc);
3739 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
3740 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
3741 surface_desc.dwBackBufferCount = 3;
3742 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
3743 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3745 memset(&surface_desc, 0, sizeof(surface_desc));
3746 surface_desc.dwSize = sizeof(surface_desc);
3747 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
3748 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3749 ok((surface_desc.ddsCaps.dwCaps & ~placement)
3750 == (DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX),
3751 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3752 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
3754 hr = IDirectDrawSurface_GetAttachedSurface(primary, &caps, &backbuffer1);
3755 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3756 memset(&surface_desc, 0, sizeof(surface_desc));
3757 surface_desc.dwSize = sizeof(surface_desc);
3758 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer1, &surface_desc);
3759 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3760 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
3761 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_BACKBUFFER),
3762 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3764 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
3765 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3766 memset(&surface_desc, 0, sizeof(surface_desc));
3767 surface_desc.dwSize = sizeof(surface_desc);
3768 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer2, &surface_desc);
3769 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3770 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
3771 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
3772 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3774 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
3775 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3776 memset(&surface_desc, 0, sizeof(surface_desc));
3777 surface_desc.dwSize = sizeof(surface_desc);
3778 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer3, &surface_desc);
3779 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3780 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
3781 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
3782 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3784 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer3, &caps, &surface);
3785 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3786 ok(surface == primary, "Got unexpected surface %p, expected %p.\n", surface, primary);
3787 IDirectDrawSurface_Release(surface);
3789 memset(&surface_desc, 0, sizeof(surface_desc));
3790 surface_desc.dwSize = sizeof(surface_desc);
3791 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3792 surface_desc.ddsCaps.dwCaps = 0;
3793 surface_desc.dwWidth = 640;
3794 surface_desc.dwHeight = 480;
3795 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3796 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3797 hr = IDirectDrawSurface_Flip(primary, surface, DDFLIP_WAIT);
3798 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3799 IDirectDrawSurface_Release(surface);
3801 hr = IDirectDrawSurface_Flip(primary, primary, DDFLIP_WAIT);
3802 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3803 hr = IDirectDrawSurface_Flip(backbuffer1, NULL, DDFLIP_WAIT);
3804 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3805 hr = IDirectDrawSurface_Flip(backbuffer2, NULL, DDFLIP_WAIT);
3806 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3807 hr = IDirectDrawSurface_Flip(backbuffer3, NULL, DDFLIP_WAIT);
3808 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3810 memset(&fx, 0, sizeof(fx));
3811 fx.dwSize = sizeof(fx);
3812 U5(fx).dwFillColor = 0xffff0000;
3813 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3814 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3815 U5(fx).dwFillColor = 0xff00ff00;
3816 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3817 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3818 U5(fx).dwFillColor = 0xff0000ff;
3819 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3820 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3822 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
3823 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3824 color = get_surface_color(backbuffer1, 320, 240);
3825 /* The testbot seems to just copy the contents of one surface to all the
3826 * others, instead of properly flipping. */
3827 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
3828 "Got unexpected color 0x%08x.\n", color);
3829 color = get_surface_color(backbuffer2, 320, 240);
3830 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
3831 U5(fx).dwFillColor = 0xffff0000;
3832 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3833 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3835 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
3836 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3837 color = get_surface_color(backbuffer1, 320, 240);
3838 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
3839 "Got unexpected color 0x%08x.\n", color);
3840 color = get_surface_color(backbuffer2, 320, 240);
3841 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
3842 U5(fx).dwFillColor = 0xff00ff00;
3843 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3844 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3846 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
3847 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3848 color = get_surface_color(backbuffer1, 320, 240);
3849 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
3850 "Got unexpected color 0x%08x.\n", color);
3851 color = get_surface_color(backbuffer2, 320, 240);
3852 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3853 U5(fx).dwFillColor = 0xff0000ff;
3854 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3855 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3857 hr = IDirectDrawSurface_Flip(primary, backbuffer1, DDFLIP_WAIT);
3858 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3859 color = get_surface_color(backbuffer2, 320, 240);
3860 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
3861 "Got unexpected color 0x%08x.\n", color);
3862 color = get_surface_color(backbuffer3, 320, 240);
3863 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
3864 U5(fx).dwFillColor = 0xffff0000;
3865 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3866 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3868 hr = IDirectDrawSurface_Flip(primary, backbuffer2, DDFLIP_WAIT);
3869 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3870 color = get_surface_color(backbuffer1, 320, 240);
3871 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
3872 color = get_surface_color(backbuffer3, 320, 240);
3873 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
3874 "Got unexpected color 0x%08x.\n", color);
3875 U5(fx).dwFillColor = 0xff00ff00;
3876 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3877 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3879 hr = IDirectDrawSurface_Flip(primary, backbuffer3, DDFLIP_WAIT);
3880 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3881 color = get_surface_color(backbuffer1, 320, 240);
3882 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
3883 "Got unexpected color 0x%08x.\n", color);
3884 color = get_surface_color(backbuffer2, 320, 240);
3885 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3887 IDirectDrawSurface_Release(backbuffer3);
3888 IDirectDrawSurface_Release(backbuffer2);
3889 IDirectDrawSurface_Release(backbuffer1);
3890 IDirectDrawSurface_Release(primary);
3891 refcount = IDirectDraw_Release(ddraw);
3892 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3893 DestroyWindow(window);
3896 static void test_sysmem_overlay(void)
3898 IDirectDraw *ddraw;
3899 HWND window;
3900 HRESULT hr;
3901 DDSURFACEDESC ddsd;
3902 IDirectDrawSurface *surface;
3903 ULONG ref;
3905 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3906 0, 0, 640, 480, 0, 0, 0, 0);
3907 ddraw = create_ddraw();
3908 ok(!!ddraw, "Failed to create a ddraw object.\n");
3910 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3911 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3913 memset(&ddsd, 0, sizeof(ddsd));
3914 ddsd.dwSize = sizeof(ddsd);
3915 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
3916 ddsd.dwWidth = 16;
3917 ddsd.dwHeight = 16;
3918 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
3919 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
3920 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
3921 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
3922 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
3923 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
3924 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
3925 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3926 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
3928 ref = IDirectDraw_Release(ddraw);
3929 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
3930 DestroyWindow(window);
3933 static void test_primary_palette(void)
3935 DDSCAPS surface_caps = {DDSCAPS_FLIP};
3936 IDirectDrawSurface *primary, *backbuffer;
3937 PALETTEENTRY palette_entries[256];
3938 IDirectDrawPalette *palette, *tmp;
3939 DDSURFACEDESC surface_desc;
3940 IDirectDraw *ddraw;
3941 DWORD palette_caps;
3942 ULONG refcount;
3943 HWND window;
3944 HRESULT hr;
3946 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3947 0, 0, 640, 480, 0, 0, 0, 0);
3948 ddraw = create_ddraw();
3949 ok(!!ddraw, "Failed to create a ddraw object.\n");
3950 if (FAILED(hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 8)))
3952 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
3953 IDirectDraw_Release(ddraw);
3954 DestroyWindow(window);
3955 return;
3957 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3958 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3959 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3961 memset(&surface_desc, 0, sizeof(surface_desc));
3962 surface_desc.dwSize = sizeof(surface_desc);
3963 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
3964 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
3965 surface_desc.dwBackBufferCount = 1;
3966 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
3967 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3968 hr = IDirectDrawSurface_GetAttachedSurface(primary, &surface_caps, &backbuffer);
3969 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3971 memset(palette_entries, 0, sizeof(palette_entries));
3972 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
3973 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
3974 refcount = get_refcount((IUnknown *)palette);
3975 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
3977 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
3978 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
3979 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
3981 hr = IDirectDrawSurface_SetPalette(primary, palette);
3982 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
3983 refcount = get_refcount((IUnknown *)palette);
3984 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
3986 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
3987 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
3988 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
3989 "Got unexpected palette caps %#x.\n", palette_caps);
3991 hr = IDirectDrawSurface_SetPalette(primary, NULL);
3992 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
3993 refcount = get_refcount((IUnknown *)palette);
3994 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
3996 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
3997 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
3998 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
4000 hr = IDirectDrawSurface_SetPalette(primary, palette);
4001 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
4002 refcount = get_refcount((IUnknown *)palette);
4003 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4005 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
4006 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
4007 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
4008 IDirectDrawPalette_Release(tmp);
4009 hr = IDirectDrawSurface_GetPalette(backbuffer, &tmp);
4010 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
4012 refcount = IDirectDrawPalette_Release(palette);
4013 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4014 refcount = IDirectDrawPalette_Release(palette);
4015 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4017 /* Note that this only seems to work when the palette is attached to the
4018 * primary surface. When attached to a regular surface, attempting to get
4019 * the palette here will cause an access violation. */
4020 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
4021 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
4023 refcount = IDirectDrawSurface_Release(backbuffer);
4024 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4025 refcount = IDirectDrawSurface_Release(primary);
4026 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4027 refcount = IDirectDraw_Release(ddraw);
4028 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4029 DestroyWindow(window);
4032 static HRESULT WINAPI surface_counter(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
4034 UINT *surface_count = context;
4036 ++(*surface_count);
4037 IDirectDrawSurface_Release(surface);
4039 return DDENUMRET_OK;
4042 static void test_surface_attachment(void)
4044 IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
4045 DDSCAPS caps = {DDSCAPS_TEXTURE};
4046 DDSURFACEDESC surface_desc;
4047 IDirectDraw *ddraw;
4048 UINT surface_count;
4049 ULONG refcount;
4050 HWND window;
4051 HRESULT hr;
4053 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4054 0, 0, 640, 480, 0, 0, 0, 0);
4055 ddraw = create_ddraw();
4056 ok(!!ddraw, "Failed to create a ddraw object.\n");
4057 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4058 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4060 memset(&surface_desc, 0, sizeof(surface_desc));
4061 surface_desc.dwSize = sizeof(surface_desc);
4062 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
4063 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
4064 U2(surface_desc).dwMipMapCount = 3;
4065 surface_desc.dwWidth = 128;
4066 surface_desc.dwHeight = 128;
4067 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4068 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4070 hr = IDirectDrawSurface_GetAttachedSurface(surface1, &caps, &surface2);
4071 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
4072 hr = IDirectDrawSurface_GetAttachedSurface(surface2, &caps, &surface3);
4073 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
4074 hr = IDirectDrawSurface_GetAttachedSurface(surface3, &caps, &surface4);
4075 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
4077 surface_count = 0;
4078 IDirectDrawSurface_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
4079 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
4080 surface_count = 0;
4081 IDirectDrawSurface_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
4082 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
4083 surface_count = 0;
4084 IDirectDrawSurface_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
4085 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
4087 memset(&surface_desc, 0, sizeof(surface_desc));
4088 surface_desc.dwSize = sizeof(surface_desc);
4089 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4090 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
4091 surface_desc.dwWidth = 16;
4092 surface_desc.dwHeight = 16;
4093 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4094 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4096 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
4097 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4098 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4099 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4100 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
4101 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4102 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
4103 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4104 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
4105 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4106 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
4107 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4109 IDirectDrawSurface_Release(surface4);
4111 memset(&surface_desc, 0, sizeof(surface_desc));
4112 surface_desc.dwSize = sizeof(surface_desc);
4113 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4114 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
4115 surface_desc.dwWidth = 16;
4116 surface_desc.dwHeight = 16;
4117 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4118 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4120 if (SUCCEEDED(hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4)))
4122 skip("Running on refrast, skipping some tests.\n");
4123 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface4);
4124 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4126 else
4128 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4129 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4130 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4131 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
4132 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4133 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
4134 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4135 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
4136 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4137 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
4138 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4141 IDirectDrawSurface_Release(surface4);
4142 IDirectDrawSurface_Release(surface3);
4143 IDirectDrawSurface_Release(surface2);
4144 IDirectDrawSurface_Release(surface1);
4146 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4147 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4149 /* Try a single primary and two offscreen plain surfaces. */
4150 memset(&surface_desc, 0, sizeof(surface_desc));
4151 surface_desc.dwSize = sizeof(surface_desc);
4152 surface_desc.dwFlags = DDSD_CAPS;
4153 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4154 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4155 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4157 memset(&surface_desc, 0, sizeof(surface_desc));
4158 surface_desc.dwSize = sizeof(surface_desc);
4159 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4160 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4161 surface_desc.dwWidth = GetSystemMetrics(SM_CXSCREEN);
4162 surface_desc.dwHeight = GetSystemMetrics(SM_CYSCREEN);
4163 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
4164 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4166 memset(&surface_desc, 0, sizeof(surface_desc));
4167 surface_desc.dwSize = sizeof(surface_desc);
4168 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4169 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4170 surface_desc.dwWidth = GetSystemMetrics(SM_CXSCREEN);
4171 surface_desc.dwHeight = GetSystemMetrics(SM_CYSCREEN);
4172 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
4173 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4175 /* This one has a different size. */
4176 memset(&surface_desc, 0, sizeof(surface_desc));
4177 surface_desc.dwSize = sizeof(surface_desc);
4178 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4179 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4180 surface_desc.dwWidth = 128;
4181 surface_desc.dwHeight = 128;
4182 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4183 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4185 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4186 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4187 /* Try the reverse without detaching first. */
4188 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
4189 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
4190 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4191 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4193 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
4194 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4195 /* Try to detach reversed. */
4196 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4197 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
4198 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
4199 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4201 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
4202 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4203 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
4204 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4206 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
4207 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4208 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4209 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4211 IDirectDrawSurface_Release(surface4);
4212 IDirectDrawSurface_Release(surface3);
4213 IDirectDrawSurface_Release(surface2);
4214 IDirectDrawSurface_Release(surface1);
4216 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
4217 memset(&surface_desc, 0, sizeof(surface_desc));
4218 surface_desc.dwSize = sizeof(surface_desc);
4219 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4220 surface_desc.dwWidth = 64;
4221 surface_desc.dwHeight = 64;
4222 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4223 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
4224 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
4225 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
4226 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
4227 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
4228 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
4229 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4230 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4231 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
4232 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4234 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4235 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
4236 U1(surface_desc.ddpfPixelFormat).dwZBufferBitDepth = 16;
4237 U3(surface_desc.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
4238 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
4239 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4241 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4242 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4243 refcount = get_refcount((IUnknown *)surface2);
4244 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4245 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4246 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
4248 /* Attaching while already attached to other surface. */
4249 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
4250 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4251 hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
4252 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4253 IDirectDrawSurface_Release(surface3);
4255 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4256 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4257 refcount = get_refcount((IUnknown *)surface2);
4258 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4260 /* Automatic detachment on release. */
4261 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4262 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4263 refcount = get_refcount((IUnknown *)surface2);
4264 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4265 refcount = IDirectDrawSurface_Release(surface1);
4266 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4267 refcount = IDirectDrawSurface_Release(surface2);
4268 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4269 refcount = IDirectDraw_Release(ddraw);
4270 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4271 DestroyWindow(window);
4274 static void test_pixel_format(void)
4276 HWND window, window2 = NULL;
4277 HDC hdc, hdc2 = NULL;
4278 HMODULE gl = NULL;
4279 int format, test_format;
4280 PIXELFORMATDESCRIPTOR pfd;
4281 IDirectDraw *ddraw = NULL;
4282 IDirectDrawClipper *clipper = NULL;
4283 DDSURFACEDESC ddsd;
4284 IDirectDrawSurface *primary = NULL;
4285 DDBLTFX fx;
4286 HRESULT hr;
4288 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4289 100, 100, 160, 160, NULL, NULL, NULL, NULL);
4290 if (!window)
4292 skip("Failed to create window\n");
4293 return;
4296 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4297 100, 100, 160, 160, NULL, NULL, NULL, NULL);
4299 hdc = GetDC(window);
4300 if (!hdc)
4302 skip("Failed to get DC\n");
4303 goto cleanup;
4306 if (window2)
4307 hdc2 = GetDC(window2);
4309 gl = LoadLibraryA("opengl32.dll");
4310 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
4312 format = GetPixelFormat(hdc);
4313 ok(format == 0, "new window has pixel format %d\n", format);
4315 ZeroMemory(&pfd, sizeof(pfd));
4316 pfd.nSize = sizeof(pfd);
4317 pfd.nVersion = 1;
4318 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
4319 pfd.iPixelType = PFD_TYPE_RGBA;
4320 pfd.iLayerType = PFD_MAIN_PLANE;
4321 format = ChoosePixelFormat(hdc, &pfd);
4322 if (format <= 0)
4324 skip("no pixel format available\n");
4325 goto cleanup;
4328 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
4330 skip("failed to set pixel format\n");
4331 goto cleanup;
4334 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
4336 skip("failed to set pixel format on second window\n");
4337 if (hdc2)
4339 ReleaseDC(window2, hdc2);
4340 hdc2 = NULL;
4344 ddraw = create_ddraw();
4345 ok(!!ddraw, "Failed to create a ddraw object.\n");
4347 test_format = GetPixelFormat(hdc);
4348 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4350 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4351 if (FAILED(hr))
4353 skip("Failed to set cooperative level, hr %#x.\n", hr);
4354 goto cleanup;
4357 test_format = GetPixelFormat(hdc);
4358 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4360 if (hdc2)
4362 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
4363 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
4364 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
4365 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
4367 test_format = GetPixelFormat(hdc);
4368 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4370 test_format = GetPixelFormat(hdc2);
4371 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4374 memset(&ddsd, 0, sizeof(ddsd));
4375 ddsd.dwSize = sizeof(ddsd);
4376 ddsd.dwFlags = DDSD_CAPS;
4377 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4379 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
4380 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4382 test_format = GetPixelFormat(hdc);
4383 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4385 if (hdc2)
4387 test_format = GetPixelFormat(hdc2);
4388 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4391 if (clipper)
4393 hr = IDirectDrawSurface_SetClipper(primary, clipper);
4394 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
4396 test_format = GetPixelFormat(hdc);
4397 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4399 test_format = GetPixelFormat(hdc2);
4400 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4403 memset(&fx, 0, sizeof(fx));
4404 fx.dwSize = sizeof(fx);
4405 hr = IDirectDrawSurface_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4406 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
4408 test_format = GetPixelFormat(hdc);
4409 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4411 if (hdc2)
4413 test_format = GetPixelFormat(hdc2);
4414 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4417 cleanup:
4418 if (primary) IDirectDrawSurface_Release(primary);
4419 if (clipper) IDirectDrawClipper_Release(clipper);
4420 if (ddraw) IDirectDraw_Release(ddraw);
4421 if (gl) FreeLibrary(gl);
4422 if (hdc) ReleaseDC(window, hdc);
4423 if (hdc2) ReleaseDC(window2, hdc2);
4424 if (window) DestroyWindow(window);
4425 if (window2) DestroyWindow(window2);
4428 static void test_create_surface_pitch(void)
4430 IDirectDrawSurface *surface;
4431 DDSURFACEDESC surface_desc;
4432 IDirectDraw *ddraw;
4433 unsigned int i;
4434 ULONG refcount;
4435 HWND window;
4436 HRESULT hr;
4437 void *mem;
4439 static const struct
4441 DWORD placement;
4442 DWORD flags_in;
4443 DWORD pitch_in;
4444 HRESULT hr;
4445 DWORD flags_out;
4446 DWORD pitch_out;
4448 test_data[] =
4450 {DDSCAPS_VIDEOMEMORY, 0, 0, DD_OK,
4451 DDSD_PITCH, 0x100},
4452 {DDSCAPS_VIDEOMEMORY, DDSD_PITCH, 0x104, DD_OK,
4453 DDSD_PITCH, 0x100},
4454 {DDSCAPS_VIDEOMEMORY, DDSD_PITCH, 0x0fc, DD_OK,
4455 DDSD_PITCH, 0x100},
4456 {DDSCAPS_VIDEOMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
4457 0, 0 },
4458 {DDSCAPS_SYSTEMMEMORY, 0, 0, DD_OK,
4459 DDSD_PITCH, 0x100},
4460 {DDSCAPS_SYSTEMMEMORY, DDSD_PITCH, 0x104, DD_OK,
4461 DDSD_PITCH, 0x100},
4462 {DDSCAPS_SYSTEMMEMORY, DDSD_PITCH, 0x0fc, DD_OK,
4463 DDSD_PITCH, 0x100},
4464 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
4465 0, 0 },
4466 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
4467 0, 0 },
4469 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE;
4471 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4472 0, 0, 640, 480, 0, 0, 0, 0);
4473 ddraw = create_ddraw();
4474 ok(!!ddraw, "Failed to create a ddraw object.\n");
4475 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4476 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4478 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((64 * 4) + 4) * 64);
4480 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
4482 memset(&surface_desc, 0, sizeof(surface_desc));
4483 surface_desc.dwSize = sizeof(surface_desc);
4484 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
4485 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | test_data[i].placement;
4486 surface_desc.dwWidth = 64;
4487 surface_desc.dwHeight = 64;
4488 U1(surface_desc).lPitch = test_data[i].pitch_in;
4489 surface_desc.lpSurface = mem;
4490 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
4491 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
4492 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
4493 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4494 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4495 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4496 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4497 ok(hr == test_data[i].hr || (test_data[i].placement == DDSCAPS_VIDEOMEMORY && hr == DDERR_NODIRECTDRAWHW),
4498 "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
4499 if (FAILED(hr))
4500 continue;
4502 memset(&surface_desc, 0, sizeof(surface_desc));
4503 surface_desc.dwSize = sizeof(surface_desc);
4504 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4505 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
4506 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
4507 "Test %u: Got unexpected flags %#x, expected %#x.\n",
4508 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
4509 ok(U1(surface_desc).lPitch == test_data[i].pitch_out,
4510 "Test %u: Got unexpected pitch %u, expected %u.\n",
4511 i, U1(surface_desc).lPitch, test_data[i].pitch_out);
4513 IDirectDrawSurface_Release(surface);
4516 HeapFree(GetProcessHeap(), 0, mem);
4517 refcount = IDirectDraw_Release(ddraw);
4518 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4519 DestroyWindow(window);
4522 static void test_mipmap_lock(void)
4524 IDirectDrawSurface *surface, *surface2;
4525 DDSURFACEDESC surface_desc;
4526 IDirectDraw *ddraw;
4527 ULONG refcount;
4528 HWND window;
4529 HRESULT hr;
4530 DDSCAPS caps = {DDSCAPS_COMPLEX};
4531 DDCAPS hal_caps;
4533 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4534 0, 0, 640, 480, 0, 0, 0, 0);
4535 ddraw = create_ddraw();
4536 ok(!!ddraw, "Failed to create a ddraw object.\n");
4537 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4538 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4540 memset(&hal_caps, 0, sizeof(hal_caps));
4541 hal_caps.dwSize = sizeof(hal_caps);
4542 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
4543 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4544 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
4546 skip("Mipmapped textures not supported, skipping mipmap lock test.\n");
4547 IDirectDraw_Release(ddraw);
4548 DestroyWindow(window);
4549 return;
4552 memset(&surface_desc, 0, sizeof(surface_desc));
4553 surface_desc.dwSize = sizeof(surface_desc);
4554 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
4555 surface_desc.dwWidth = 4;
4556 surface_desc.dwHeight = 4;
4557 U2(surface_desc).dwMipMapCount = 2;
4558 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
4559 | DDSCAPS_SYSTEMMEMORY;
4560 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4561 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4562 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &surface2);
4563 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4565 memset(&surface_desc, 0, sizeof(surface_desc));
4566 surface_desc.dwSize = sizeof(surface_desc);
4567 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, 0, NULL);
4568 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4569 memset(&surface_desc, 0, sizeof(surface_desc));
4570 surface_desc.dwSize = sizeof(surface_desc);
4571 hr = IDirectDrawSurface_Lock(surface2, NULL, &surface_desc, 0, NULL);
4572 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4573 IDirectDrawSurface_Unlock(surface2, NULL);
4574 IDirectDrawSurface_Unlock(surface, NULL);
4576 IDirectDrawSurface_Release(surface2);
4577 IDirectDrawSurface_Release(surface);
4578 refcount = IDirectDraw_Release(ddraw);
4579 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4580 DestroyWindow(window);
4583 START_TEST(ddraw1)
4585 IDirectDraw *ddraw;
4587 if (!(ddraw = create_ddraw()))
4589 skip("Failed to create a ddraw object, skipping tests.\n");
4590 return;
4592 IDirectDraw_Release(ddraw);
4594 test_coop_level_create_device_window();
4595 test_clipper_blt();
4596 test_coop_level_d3d_state();
4597 test_surface_interface_mismatch();
4598 test_coop_level_threaded();
4599 test_viewport();
4600 test_zenable();
4601 test_ck_rgba();
4602 test_ck_default();
4603 test_ck_complex();
4604 test_surface_qi();
4605 test_device_qi();
4606 test_wndproc();
4607 test_window_style();
4608 test_redundant_mode_set();
4609 test_coop_level_mode_set();
4610 test_coop_level_mode_set_multi();
4611 test_initialize();
4612 test_coop_level_surf_create();
4613 test_coop_level_multi_window();
4614 test_clear_rect_count();
4615 test_coop_level_activateapp();
4616 test_unsupported_formats();
4617 test_rt_caps();
4618 test_primary_caps();
4619 test_surface_lock();
4620 test_surface_discard();
4621 test_flip();
4622 test_sysmem_overlay();
4623 test_primary_palette();
4624 test_surface_attachment();
4625 test_pixel_format();
4626 test_create_surface_pitch();
4627 test_mipmap_lock();