user32: Added RegisterPowerSettingNotification() stub.
[wine/wine-gecko.git] / dlls / ddraw / tests / ddraw1.c
blob52f60af19a2b504730035a5fa5c172a32108ecf4
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 static const D3DCOLOR expected2[] =
561 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
562 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
563 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
564 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
567 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
568 10, 10, 640, 480, 0, 0, 0, 0);
569 ShowWindow(window, SW_SHOW);
570 ddraw = create_ddraw();
571 ok(!!ddraw, "Failed to create a ddraw object.\n");
573 ret = GetClientRect(window, &client_rect);
574 ok(ret, "Failed to get client rect.\n");
575 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
576 ok(ret, "Failed to map client rect.\n");
578 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
579 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
581 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
582 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
583 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
584 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
585 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
586 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
587 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
588 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
589 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
590 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
591 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
592 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
593 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
594 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
595 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
596 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
597 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
598 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
599 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
600 HeapFree(GetProcessHeap(), 0, rgn_data);
602 r1 = CreateRectRgn(0, 0, 320, 240);
603 ok(!!r1, "Failed to create region.\n");
604 r2 = CreateRectRgn(320, 240, 640, 480);
605 ok(!!r2, "Failed to create region.\n");
606 CombineRgn(r1, r1, r2, RGN_OR);
607 ret = GetRegionData(r1, 0, NULL);
608 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
609 ret = GetRegionData(r1, ret, rgn_data);
610 ok(!!ret, "Failed to get region data.\n");
612 DeleteObject(r2);
613 DeleteObject(r1);
615 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
616 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
617 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
618 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
619 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
620 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
622 HeapFree(GetProcessHeap(), 0, rgn_data);
624 memset(&surface_desc, 0, sizeof(surface_desc));
625 surface_desc.dwSize = sizeof(surface_desc);
626 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
627 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
628 surface_desc.dwWidth = 640;
629 surface_desc.dwHeight = 480;
630 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
631 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
632 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
633 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
634 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
635 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
637 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
638 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
639 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
640 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
642 memset(&fx, 0, sizeof(fx));
643 fx.dwSize = sizeof(fx);
644 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
645 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
646 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
647 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
649 hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
650 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
651 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
652 ptr = surface_desc.lpSurface;
653 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
654 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
655 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
656 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
657 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
659 hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
660 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
662 SetRect(&src_rect, 1, 1, 5, 2);
663 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
664 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
665 for (i = 0; i < 4; ++i)
667 for (j = 0; j < 4; ++j)
669 x = 80 * ((2 * j) + 1);
670 y = 60 * ((2 * i) + 1);
671 color = get_surface_color(dst_surface, x, y);
672 ok(compare_color(color, expected1[i * 4 + j], 1),
673 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
677 U5(fx).dwFillColor = 0xff0000ff;
678 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
679 ok(SUCCEEDED(hr), "Failed to clear destination surface, 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, expected2[i * 4 + j], 1),
688 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
692 hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
693 ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
695 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
696 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
697 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
698 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
699 DestroyWindow(window);
700 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
701 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
702 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
703 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
704 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
705 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
706 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
707 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
708 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
709 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
710 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
711 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
713 IDirectDrawSurface_Release(dst_surface);
714 IDirectDrawSurface_Release(src_surface);
715 IDirectDrawClipper_Release(clipper);
716 IDirectDraw_Release(ddraw);
719 static void test_coop_level_d3d_state(void)
721 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
722 IDirectDrawSurface *rt, *surface;
723 IDirect3DMaterial *background;
724 IDirect3DViewport *viewport;
725 IDirect3DDevice *device;
726 D3DMATERIAL material;
727 IDirectDraw *ddraw;
728 D3DCOLOR color;
729 HWND window;
730 HRESULT hr;
732 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
733 0, 0, 640, 480, 0, 0, 0, 0);
734 ddraw = create_ddraw();
735 ok(!!ddraw, "Failed to create a ddraw object.\n");
736 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
738 skip("Failed to create a 3D device, skipping test.\n");
739 IDirectDraw_Release(ddraw);
740 DestroyWindow(window);
741 return;
744 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
745 viewport = create_viewport(device, 0, 0, 640, 480);
746 viewport_set_background(device, viewport, background);
748 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
749 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
750 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
751 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
752 color = get_surface_color(rt, 320, 240);
753 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
755 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
756 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
757 hr = IDirectDrawSurface_IsLost(rt);
758 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
759 hr = restore_surfaces(ddraw);
760 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
762 memset(&material, 0, sizeof(material));
763 material.dwSize = sizeof(material);
764 U1(U(material).diffuse).r = 0.0f;
765 U2(U(material).diffuse).g = 1.0f;
766 U3(U(material).diffuse).b = 0.0f;
767 U4(U(material).diffuse).a = 1.0f;
768 hr = IDirect3DMaterial_SetMaterial(background, &material);
769 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
771 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&surface);
772 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
773 ok(surface == rt, "Got unexpected surface %p.\n", surface);
774 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
775 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
776 color = get_surface_color(rt, 320, 240);
777 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
779 destroy_viewport(device, viewport);
780 destroy_material(background);
781 IDirectDrawSurface_Release(surface);
782 IDirectDrawSurface_Release(rt);
783 IDirect3DDevice_Release(device);
784 IDirectDraw_Release(ddraw);
785 DestroyWindow(window);
788 static void test_surface_interface_mismatch(void)
790 IDirectDraw *ddraw = NULL;
791 IDirectDrawSurface *surface = NULL, *ds;
792 IDirectDrawSurface3 *surface3 = NULL;
793 IDirect3DDevice *device = NULL;
794 IDirect3DViewport *viewport = NULL;
795 IDirect3DMaterial *background = NULL;
796 DDSURFACEDESC surface_desc;
797 DWORD z_depth = 0;
798 ULONG refcount;
799 HRESULT hr;
800 D3DCOLOR color;
801 HWND window;
802 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
804 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
805 0, 0, 640, 480, 0, 0, 0, 0);
806 ddraw = create_ddraw();
807 ok(!!ddraw, "Failed to create a ddraw object.\n");
808 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
810 skip("Failed to create a 3D device, skipping test.\n");
811 IDirectDraw_Release(ddraw);
812 DestroyWindow(window);
813 return;
815 z_depth = get_device_z_depth(device);
816 ok(!!z_depth, "Failed to get device z depth.\n");
817 IDirect3DDevice_Release(device);
818 device = NULL;
820 memset(&surface_desc, 0, sizeof(surface_desc));
821 surface_desc.dwSize = sizeof(surface_desc);
822 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
823 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
824 surface_desc.dwWidth = 640;
825 surface_desc.dwHeight = 480;
827 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
828 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
830 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
831 if (FAILED(hr))
833 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
834 goto cleanup;
837 memset(&surface_desc, 0, sizeof(surface_desc));
838 surface_desc.dwSize = sizeof(surface_desc);
839 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
840 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
841 U2(surface_desc).dwZBufferBitDepth = z_depth;
842 surface_desc.dwWidth = 640;
843 surface_desc.dwHeight = 480;
844 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL);
845 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
846 if (FAILED(hr))
847 goto cleanup;
849 /* Using a different surface interface version still works */
850 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
851 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
852 refcount = IDirectDrawSurface_Release(ds);
853 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
854 if (FAILED(hr))
855 goto cleanup;
857 /* Here too */
858 hr = IDirectDrawSurface3_QueryInterface(surface3, &IID_IDirect3DHALDevice, (void **)&device);
859 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
860 if (FAILED(hr))
861 goto cleanup;
863 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
864 viewport = create_viewport(device, 0, 0, 640, 480);
865 viewport_set_background(device, viewport, background);
867 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
868 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
869 color = get_surface_color(surface, 320, 240);
870 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
872 cleanup:
873 if (viewport)
874 destroy_viewport(device, viewport);
875 if (background)
876 destroy_material(background);
877 if (surface3) IDirectDrawSurface3_Release(surface3);
878 if (surface) IDirectDrawSurface_Release(surface);
879 if (device) IDirect3DDevice_Release(device);
880 if (ddraw) IDirectDraw_Release(ddraw);
881 DestroyWindow(window);
884 static void test_coop_level_threaded(void)
886 struct create_window_thread_param p;
887 IDirectDraw *ddraw;
888 HRESULT hr;
890 ddraw = create_ddraw();
891 ok(!!ddraw, "Failed to create a ddraw object.\n");
892 create_window_thread(&p);
894 hr = IDirectDraw_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
895 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
897 IDirectDraw_Release(ddraw);
898 destroy_window_thread(&p);
901 static ULONG get_refcount(IUnknown *test_iface)
903 IUnknown_AddRef(test_iface);
904 return IUnknown_Release(test_iface);
907 static void test_viewport(void)
909 IDirectDraw *ddraw;
910 IDirect3D *d3d;
911 HRESULT hr;
912 ULONG ref;
913 IDirect3DViewport *viewport, *another_vp;
914 IDirect3DViewport2 *viewport2;
915 IDirect3DViewport3 *viewport3;
916 IDirectDrawGammaControl *gamma;
917 IUnknown *unknown;
918 IDirect3DDevice *device;
919 HWND window;
921 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
922 0, 0, 640, 480, 0, 0, 0, 0);
923 ddraw = create_ddraw();
924 ok(!!ddraw, "Failed to create a ddraw object.\n");
925 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
927 skip("Failed to create a 3D device, skipping test.\n");
928 IDirectDraw_Release(ddraw);
929 DestroyWindow(window);
930 return;
933 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
934 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
935 ref = get_refcount((IUnknown *) d3d);
936 ok(ref == 2, "IDirect3D refcount is %d\n", ref);
938 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
939 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
940 ref = get_refcount((IUnknown *)viewport);
941 ok(ref == 1, "Initial IDirect3DViewport refcount is %u\n", ref);
942 ref = get_refcount((IUnknown *)d3d);
943 ok(ref == 2, "IDirect3D refcount is %u\n", ref);
945 /* E_FAIL return values are returned by Winetestbot Windows NT machines. While not supporting
946 * newer interfaces is legitimate for old ddraw versions, E_FAIL violates Microsoft's rules
947 * for QueryInterface, hence the broken() */
948 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
949 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirectDrawGammaControl, (void **)&gamma);
950 ok(hr == E_NOINTERFACE || broken(hr == E_FAIL), "Got unexpected hr %#x.\n", hr);
951 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
952 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
953 /* NULL iid: Segfaults */
955 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport2, (void **)&viewport2);
956 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
957 "Failed to QI IDirect3DViewport2, hr %#x.\n", hr);
958 if (viewport2)
960 ref = get_refcount((IUnknown *)viewport);
961 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
962 ref = get_refcount((IUnknown *)viewport2);
963 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
964 IDirect3DViewport2_Release(viewport2);
965 viewport2 = NULL;
968 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport3, (void **)&viewport3);
969 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
970 "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
971 if (viewport3)
973 ref = get_refcount((IUnknown *)viewport);
974 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
975 ref = get_refcount((IUnknown *)viewport3);
976 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
977 IDirect3DViewport3_Release(viewport3);
980 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IUnknown, (void **)&unknown);
981 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
982 if (unknown)
984 ref = get_refcount((IUnknown *)viewport);
985 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
986 ref = get_refcount(unknown);
987 ok(ref == 2, "IUnknown refcount is %u\n", ref);
988 IUnknown_Release(unknown);
991 /* AddViewport(NULL): Segfault */
992 hr = IDirect3DDevice_DeleteViewport(device, NULL);
993 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
995 hr = IDirect3D_CreateViewport(d3d, &another_vp, NULL);
996 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
998 hr = IDirect3DDevice_AddViewport(device, viewport);
999 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1000 ref = get_refcount((IUnknown *) viewport);
1001 ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
1002 hr = IDirect3DDevice_AddViewport(device, another_vp);
1003 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1004 ref = get_refcount((IUnknown *) another_vp);
1005 ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
1007 hr = IDirect3DDevice_DeleteViewport(device, another_vp);
1008 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1009 ref = get_refcount((IUnknown *) another_vp);
1010 ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
1012 IDirect3DDevice_Release(device);
1013 ref = get_refcount((IUnknown *) viewport);
1014 ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
1016 IDirect3DViewport_Release(another_vp);
1017 IDirect3D_Release(d3d);
1018 IDirect3DViewport_Release(viewport);
1019 DestroyWindow(window);
1020 IDirectDraw_Release(ddraw);
1023 static void test_zenable(void)
1025 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1026 static D3DTLVERTEX tquad[] =
1028 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1029 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1030 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1031 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1033 IDirect3DExecuteBuffer *execute_buffer;
1034 D3DEXECUTEBUFFERDESC exec_desc;
1035 IDirect3DMaterial *background;
1036 IDirect3DViewport *viewport;
1037 IDirect3DDevice *device;
1038 IDirectDrawSurface *rt;
1039 IDirectDraw *ddraw;
1040 UINT inst_length;
1041 D3DCOLOR color;
1042 HWND window;
1043 HRESULT hr;
1044 UINT x, y;
1045 UINT i, j;
1046 void *ptr;
1048 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1049 0, 0, 640, 480, 0, 0, 0, 0);
1050 ddraw = create_ddraw();
1051 ok(!!ddraw, "Failed to create a ddraw object.\n");
1052 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1054 skip("Failed to create a 3D device, skipping test.\n");
1055 IDirectDraw_Release(ddraw);
1056 DestroyWindow(window);
1057 return;
1060 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1061 viewport = create_viewport(device, 0, 0, 640, 480);
1062 viewport_set_background(device, viewport, background);
1064 memset(&exec_desc, 0, sizeof(exec_desc));
1065 exec_desc.dwSize = sizeof(exec_desc);
1066 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1067 exec_desc.dwBufferSize = 1024;
1068 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1070 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1071 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1072 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1073 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1074 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1075 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1076 emit_process_vertices(&ptr, 0, 4);
1077 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1078 emit_tquad(&ptr, 0);
1079 emit_end(&ptr);
1080 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
1081 inst_length -= sizeof(tquad);
1082 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1083 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1085 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1086 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1087 hr = IDirect3DDevice_BeginScene(device);
1088 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1089 set_execute_data(execute_buffer, 4, sizeof(tquad), inst_length);
1090 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1091 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1092 hr = IDirect3DDevice_EndScene(device);
1093 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1095 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1096 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1097 for (i = 0; i < 4; ++i)
1099 for (j = 0; j < 4; ++j)
1101 x = 80 * ((2 * j) + 1);
1102 y = 60 * ((2 * i) + 1);
1103 color = get_surface_color(rt, x, y);
1104 ok(compare_color(color, 0x0000ff00, 1),
1105 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1108 IDirectDrawSurface_Release(rt);
1110 destroy_viewport(device, viewport);
1111 IDirect3DExecuteBuffer_Release(execute_buffer);
1112 destroy_material(background);
1113 IDirect3DDevice_Release(device);
1114 IDirectDraw_Release(ddraw);
1115 DestroyWindow(window);
1118 static void test_ck_rgba(void)
1120 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1121 static D3DTLVERTEX tquad[] =
1123 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1124 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1125 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1126 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1127 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1128 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1129 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1130 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1132 static const struct
1134 D3DCOLOR fill_color;
1135 BOOL color_key;
1136 BOOL blend;
1137 D3DCOLOR result1;
1138 D3DCOLOR result2;
1140 tests[] =
1142 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x000000ff},
1143 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x000000ff},
1144 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00},
1145 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1146 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00807f00},
1147 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x0000ff00},
1148 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00},
1149 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1152 IDirect3DExecuteBuffer *execute_buffer;
1153 D3DTEXTUREHANDLE texture_handle;
1154 D3DEXECUTEBUFFERDESC exec_desc;
1155 IDirect3DMaterial *background;
1156 IDirectDrawSurface *surface;
1157 IDirect3DViewport *viewport;
1158 DDSURFACEDESC surface_desc;
1159 IDirect3DTexture *texture;
1160 IDirect3DDevice *device;
1161 IDirectDrawSurface *rt;
1162 IDirectDraw *ddraw;
1163 D3DCOLOR color;
1164 HWND window;
1165 DDBLTFX fx;
1166 HRESULT hr;
1167 UINT i;
1169 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1170 0, 0, 640, 480, 0, 0, 0, 0);
1171 ddraw = create_ddraw();
1172 ok(!!ddraw, "Failed to create a ddraw object.\n");
1173 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1175 skip("Failed to create a 3D device, skipping test.\n");
1176 IDirectDraw_Release(ddraw);
1177 DestroyWindow(window);
1178 return;
1181 background = create_diffuse_material(device, 1.0, 0.0f, 0.0f, 1.0f);
1182 viewport = create_viewport(device, 0, 0, 640, 480);
1183 viewport_set_background(device, viewport, background);
1185 memset(&surface_desc, 0, sizeof(surface_desc));
1186 surface_desc.dwSize = sizeof(surface_desc);
1187 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1188 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1189 surface_desc.dwWidth = 256;
1190 surface_desc.dwHeight = 256;
1191 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1192 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1193 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1194 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1195 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1196 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1197 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1198 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1199 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1200 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1201 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1202 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1203 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1204 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1205 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1206 IDirect3DTexture_Release(texture);
1208 memset(&exec_desc, 0, sizeof(exec_desc));
1209 exec_desc.dwSize = sizeof(exec_desc);
1210 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1211 exec_desc.dwBufferSize = 1024;
1212 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1213 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1214 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1216 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1217 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1219 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1221 UINT draw1_len, draw2_len;
1222 void *ptr;
1224 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1225 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1226 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1227 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1228 emit_process_vertices(&ptr, 0, 4);
1229 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1230 emit_set_rs(&ptr, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1231 emit_set_rs(&ptr, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1232 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1233 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1234 emit_tquad(&ptr, 0);
1235 emit_end(&ptr);
1236 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - sizeof(tquad);
1237 emit_process_vertices(&ptr, 4, 4);
1238 emit_tquad(&ptr, 0);
1239 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1240 emit_end(&ptr);
1241 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_len;
1242 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1243 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1245 memset(&fx, 0, sizeof(fx));
1246 fx.dwSize = sizeof(fx);
1247 U5(fx).dwFillColor = tests[i].fill_color;
1248 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1249 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1251 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1252 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1253 hr = IDirect3DDevice_BeginScene(device);
1254 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1255 set_execute_data(execute_buffer, 8, sizeof(tquad), draw1_len);
1256 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1257 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1258 hr = IDirect3DDevice_EndScene(device);
1259 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1261 color = get_surface_color(rt, 320, 240);
1262 if (i == 2)
1263 todo_wine ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1264 tests[i].result1, i, color);
1265 else
1266 ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1267 tests[i].result1, i, color);
1269 U5(fx).dwFillColor = 0xff0000ff;
1270 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1271 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1273 hr = IDirect3DDevice_BeginScene(device);
1274 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1275 set_execute_data(execute_buffer, 8, sizeof(tquad) + draw1_len, draw2_len);
1276 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1277 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1278 hr = IDirect3DDevice_EndScene(device);
1279 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1281 /* This tests that fragments that are masked out by the color key are
1282 * discarded, instead of just fully transparent. */
1283 color = get_surface_color(rt, 320, 240);
1284 if (i == 2)
1285 todo_wine ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1286 tests[i].result2, i, color);
1287 else
1288 ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1289 tests[i].result2, i, color);
1292 IDirectDrawSurface_Release(rt);
1293 IDirect3DExecuteBuffer_Release(execute_buffer);
1294 IDirectDrawSurface_Release(surface);
1295 destroy_viewport(device, viewport);
1296 destroy_material(background);
1297 IDirect3DDevice_Release(device);
1298 IDirectDraw_Release(ddraw);
1299 DestroyWindow(window);
1302 static void test_ck_default(void)
1304 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1305 static D3DTLVERTEX tquad[] =
1307 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1308 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1309 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1310 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1312 IDirect3DExecuteBuffer *execute_buffer;
1313 IDirectDrawSurface *surface, *rt;
1314 D3DTEXTUREHANDLE texture_handle;
1315 D3DEXECUTEBUFFERDESC exec_desc;
1316 IDirect3DMaterial *background;
1317 UINT draw1_offset, draw1_len;
1318 UINT draw2_offset, draw2_len;
1319 UINT draw3_offset, draw3_len;
1320 UINT draw4_offset, draw4_len;
1321 IDirect3DViewport *viewport;
1322 DDSURFACEDESC surface_desc;
1323 IDirect3DTexture *texture;
1324 IDirect3DDevice *device;
1325 IDirectDraw *ddraw;
1326 D3DCOLOR color;
1327 HWND window;
1328 DDBLTFX fx;
1329 HRESULT hr;
1330 void *ptr;
1332 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1333 0, 0, 640, 480, 0, 0, 0, 0);
1334 ddraw = create_ddraw();
1335 ok(!!ddraw, "Failed to create a ddraw object.\n");
1336 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1338 skip("Failed to create a 3D device, skipping test.\n");
1339 IDirectDraw_Release(ddraw);
1340 DestroyWindow(window);
1341 return;
1344 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1345 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1347 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
1348 viewport = create_viewport(device, 0, 0, 640, 480);
1349 viewport_set_background(device, viewport, background);
1351 memset(&surface_desc, 0, sizeof(surface_desc));
1352 surface_desc.dwSize = sizeof(surface_desc);
1353 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1354 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1355 surface_desc.dwWidth = 256;
1356 surface_desc.dwHeight = 256;
1357 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1358 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1359 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1360 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1361 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1362 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1363 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1364 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1365 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1366 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1367 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1368 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1369 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1370 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1371 IDirect3DTexture_Release(texture);
1373 memset(&fx, 0, sizeof(fx));
1374 fx.dwSize = sizeof(fx);
1375 U5(fx).dwFillColor = 0x000000ff;
1376 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1377 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1379 memset(&exec_desc, 0, sizeof(exec_desc));
1380 exec_desc.dwSize = sizeof(exec_desc);
1381 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1382 exec_desc.dwBufferSize = 1024;
1383 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1384 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1385 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1387 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1388 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1389 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1390 ptr = (BYTE *)exec_desc.lpData + sizeof(tquad);
1391 emit_process_vertices(&ptr, 0, 4);
1392 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1393 emit_tquad(&ptr, 0);
1394 emit_end(&ptr);
1395 draw1_offset = sizeof(tquad);
1396 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_offset;
1397 emit_process_vertices(&ptr, 0, 4);
1398 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, FALSE);
1399 emit_tquad(&ptr, 0);
1400 emit_end(&ptr);
1401 draw2_offset = draw1_offset + draw1_len;
1402 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw2_offset;
1403 emit_process_vertices(&ptr, 0, 4);
1404 emit_tquad(&ptr, 0);
1405 emit_end(&ptr);
1406 draw3_offset = draw2_offset + draw2_len;
1407 draw3_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw3_offset;
1408 emit_process_vertices(&ptr, 0, 4);
1409 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1410 emit_tquad(&ptr, 0);
1411 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1412 emit_end(&ptr);
1413 draw4_offset = draw3_offset + draw3_len;
1414 draw4_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw4_offset;
1415 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1416 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1418 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1419 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1420 hr = IDirect3DDevice_BeginScene(device);
1421 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1422 set_execute_data(execute_buffer, 4, draw1_offset, draw1_len);
1423 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1424 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1425 hr = IDirect3DDevice_EndScene(device);
1426 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1427 color = get_surface_color(rt, 320, 240);
1428 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1430 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1431 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1432 hr = IDirect3DDevice_BeginScene(device);
1433 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1434 set_execute_data(execute_buffer, 4, draw2_offset, draw2_len);
1435 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1436 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1437 hr = IDirect3DDevice_EndScene(device);
1438 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1439 color = get_surface_color(rt, 320, 240);
1440 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1442 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1443 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1444 hr = IDirect3DDevice_BeginScene(device);
1445 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1446 set_execute_data(execute_buffer, 4, draw3_offset, draw3_len);
1447 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1448 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1449 hr = IDirect3DDevice_EndScene(device);
1450 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1451 color = get_surface_color(rt, 320, 240);
1452 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1454 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1455 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1456 hr = IDirect3DDevice_BeginScene(device);
1457 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1458 set_execute_data(execute_buffer, 4, draw4_offset, draw4_len);
1459 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1460 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1461 hr = IDirect3DDevice_EndScene(device);
1462 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1463 color = get_surface_color(rt, 320, 240);
1464 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1466 IDirect3DExecuteBuffer_Release(execute_buffer);
1467 IDirectDrawSurface_Release(surface);
1468 destroy_viewport(device, viewport);
1469 destroy_material(background);
1470 IDirectDrawSurface_Release(rt);
1471 IDirect3DDevice_Release(device);
1472 IDirectDraw_Release(ddraw);
1473 DestroyWindow(window);
1476 static void test_ck_complex(void)
1478 IDirectDrawSurface *surface, *mipmap, *tmp;
1479 DDSCAPS caps = {DDSCAPS_COMPLEX};
1480 DDSURFACEDESC surface_desc;
1481 IDirect3DDevice *device;
1482 DDCOLORKEY color_key;
1483 IDirectDraw *ddraw;
1484 unsigned int i;
1485 ULONG refcount;
1486 HWND window;
1487 HRESULT hr;
1489 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1490 0, 0, 640, 480, 0, 0, 0, 0);
1491 ddraw = create_ddraw();
1492 ok(!!ddraw, "Failed to create a ddraw object.\n");
1493 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1495 skip("Failed to create a 3D device, skipping test.\n");
1496 DestroyWindow(window);
1497 IDirectDraw2_Release(ddraw);
1498 return;
1500 IDirect3DDevice_Release(device);
1502 memset(&surface_desc, 0, sizeof(surface_desc));
1503 surface_desc.dwSize = sizeof(surface_desc);
1504 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1505 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1506 surface_desc.dwWidth = 128;
1507 surface_desc.dwHeight = 128;
1508 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1509 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1511 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1512 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1513 color_key.dwColorSpaceLowValue = 0x0000ff00;
1514 color_key.dwColorSpaceHighValue = 0x0000ff00;
1515 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1516 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1517 memset(&color_key, 0, sizeof(color_key));
1518 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1519 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1520 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1521 color_key.dwColorSpaceLowValue);
1522 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1523 color_key.dwColorSpaceHighValue);
1525 mipmap = surface;
1526 IDirectDrawSurface_AddRef(mipmap);
1527 for (i = 0; i < 7; ++i)
1529 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1530 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1532 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1533 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1534 color_key.dwColorSpaceLowValue = 0x000000ff;
1535 color_key.dwColorSpaceHighValue = 0x000000ff;
1536 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1537 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x, i %u.\n", hr, i);
1538 memset(&color_key, 0, sizeof(color_key));
1539 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1540 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x, i %u.\n", hr, i);
1541 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1542 color_key.dwColorSpaceLowValue, i);
1543 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1544 color_key.dwColorSpaceHighValue, i);
1546 IDirectDrawSurface_Release(mipmap);
1547 mipmap = tmp;
1550 memset(&color_key, 0, sizeof(color_key));
1551 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1552 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1553 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1554 color_key.dwColorSpaceLowValue);
1555 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1556 color_key.dwColorSpaceHighValue);
1558 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1559 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1560 IDirectDrawSurface_Release(mipmap);
1561 refcount = IDirectDrawSurface_Release(surface);
1562 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1564 memset(&surface_desc, 0, sizeof(surface_desc));
1565 surface_desc.dwSize = sizeof(surface_desc);
1566 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1567 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1568 surface_desc.dwBackBufferCount = 1;
1569 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1570 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1572 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1573 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1574 color_key.dwColorSpaceLowValue = 0x0000ff00;
1575 color_key.dwColorSpaceHighValue = 0x0000ff00;
1576 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1577 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1578 memset(&color_key, 0, sizeof(color_key));
1579 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1580 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1581 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1582 color_key.dwColorSpaceLowValue);
1583 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1584 color_key.dwColorSpaceHighValue);
1586 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
1587 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1589 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1590 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1591 color_key.dwColorSpaceLowValue = 0x0000ff00;
1592 color_key.dwColorSpaceHighValue = 0x0000ff00;
1593 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1594 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1595 memset(&color_key, 0, sizeof(color_key));
1596 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1597 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1598 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1599 color_key.dwColorSpaceLowValue);
1600 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1601 color_key.dwColorSpaceHighValue);
1603 IDirectDrawSurface_Release(tmp);
1605 refcount = IDirectDrawSurface_Release(surface);
1606 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1607 refcount = IDirectDraw_Release(ddraw);
1608 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1609 DestroyWindow(window);
1612 struct qi_test
1614 REFIID iid;
1615 REFIID refcount_iid;
1616 HRESULT hr;
1619 static void test_qi(const char *test_name, IUnknown *base_iface,
1620 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1622 ULONG refcount, expected_refcount;
1623 IUnknown *iface1, *iface2;
1624 HRESULT hr;
1625 UINT i, j;
1627 for (i = 0; i < entry_count; ++i)
1629 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1630 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1631 if (SUCCEEDED(hr))
1633 for (j = 0; j < entry_count; ++j)
1635 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1636 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1637 if (SUCCEEDED(hr))
1639 expected_refcount = 0;
1640 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1641 ++expected_refcount;
1642 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1643 ++expected_refcount;
1644 refcount = IUnknown_Release(iface2);
1645 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1646 refcount, test_name, i, j, expected_refcount);
1650 expected_refcount = 0;
1651 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1652 ++expected_refcount;
1653 refcount = IUnknown_Release(iface1);
1654 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1655 refcount, test_name, i, expected_refcount);
1660 static void test_surface_qi(void)
1662 static const struct qi_test tests[] =
1664 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1665 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1666 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1667 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1668 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1669 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1670 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1671 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1672 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1673 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1674 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1675 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1676 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1677 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1678 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1679 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1680 {&IID_IDirect3D, NULL, E_INVALIDARG },
1681 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1682 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1683 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1684 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1685 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1686 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1687 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1688 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1689 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1690 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1691 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1692 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1693 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1694 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1695 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1696 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1697 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1698 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1701 IDirectDrawSurface *surface;
1702 DDSURFACEDESC surface_desc;
1703 IDirect3DDevice *device;
1704 IDirectDraw *ddraw;
1705 HWND window;
1706 HRESULT hr;
1708 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1710 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1711 return;
1714 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1715 0, 0, 640, 480, 0, 0, 0, 0);
1716 ddraw = create_ddraw();
1717 ok(!!ddraw, "Failed to create a ddraw object.\n");
1718 /* Try to create a D3D device to see if the ddraw implementation supports
1719 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1720 * doesn't support e.g. the IDirect3DTexture interfaces. */
1721 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1723 skip("Failed to create a 3D device, skipping test.\n");
1724 IDirectDraw_Release(ddraw);
1725 DestroyWindow(window);
1726 return;
1728 IDirect3DDevice_Release(device);
1730 memset(&surface_desc, 0, sizeof(surface_desc));
1731 surface_desc.dwSize = sizeof(surface_desc);
1732 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1733 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1734 surface_desc.dwWidth = 512;
1735 surface_desc.dwHeight = 512;
1736 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1737 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1739 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1741 IDirectDrawSurface_Release(surface);
1742 IDirectDraw_Release(ddraw);
1743 DestroyWindow(window);
1746 static void test_device_qi(void)
1748 static const struct qi_test tests[] =
1750 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1751 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1752 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1753 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1754 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1755 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1756 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1757 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1758 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1759 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1760 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1761 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1762 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1763 {&IID_IDirect3DHALDevice, &IID_IDirectDrawSurface, S_OK },
1764 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1765 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1766 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1767 {&IID_IDirect3D, NULL, E_INVALIDARG },
1768 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1769 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1770 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1771 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1772 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1773 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1774 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1775 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1776 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1777 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1778 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1779 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1780 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1781 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1782 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1783 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1784 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1785 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1789 IDirect3DDevice *device;
1790 IDirectDraw *ddraw;
1791 HWND window;
1793 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1795 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1796 return;
1799 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1800 0, 0, 640, 480, 0, 0, 0, 0);
1801 ddraw = create_ddraw();
1802 ok(!!ddraw, "Failed to create a ddraw object.\n");
1803 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1805 skip("Failed to create a 3D device, skipping test.\n");
1806 IDirectDraw_Release(ddraw);
1807 DestroyWindow(window);
1808 return;
1811 test_qi("device_qi", (IUnknown *)device, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1813 IDirect3DDevice_Release(device);
1814 IDirectDraw_Release(ddraw);
1815 DestroyWindow(window);
1818 static void test_wndproc(void)
1820 LONG_PTR proc, ddraw_proc;
1821 IDirectDraw *ddraw;
1822 WNDCLASSA wc = {0};
1823 HWND window;
1824 HRESULT hr;
1825 ULONG ref;
1827 static const UINT messages[] =
1829 WM_WINDOWPOSCHANGING,
1830 WM_MOVE,
1831 WM_SIZE,
1832 WM_WINDOWPOSCHANGING,
1833 WM_ACTIVATE,
1834 WM_SETFOCUS,
1838 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
1839 ddraw = create_ddraw();
1840 ok(!!ddraw, "Failed to create a ddraw object.\n");
1842 wc.lpfnWndProc = test_proc;
1843 wc.lpszClassName = "ddraw_test_wndproc_wc";
1844 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1846 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
1847 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
1849 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1850 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1851 (LONG_PTR)test_proc, proc);
1852 expect_messages = messages;
1853 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1854 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1855 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
1856 expect_messages = NULL;
1857 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1858 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1859 (LONG_PTR)test_proc, proc);
1860 ref = IDirectDraw_Release(ddraw);
1861 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1862 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1863 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1864 (LONG_PTR)test_proc, proc);
1866 /* DDSCL_NORMAL doesn't. */
1867 ddraw = create_ddraw();
1868 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1869 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1870 (LONG_PTR)test_proc, proc);
1871 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
1872 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
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 /* The original window proc is only restored by ddraw if the current
1883 * window proc matches the one ddraw set. This also affects switching
1884 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
1885 ddraw = create_ddraw();
1886 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1887 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1888 (LONG_PTR)test_proc, proc);
1889 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1890 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1891 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1892 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1893 (LONG_PTR)test_proc, proc);
1894 ddraw_proc = proc;
1895 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1896 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1897 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1898 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1899 (LONG_PTR)test_proc, proc);
1900 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1901 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1902 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
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_NORMAL);
1906 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1907 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1908 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1909 (LONG_PTR)DefWindowProcA, proc);
1910 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1911 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1912 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
1913 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1914 (LONG_PTR)DefWindowProcA, proc);
1915 ref = IDirectDraw_Release(ddraw);
1916 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1917 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1918 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1919 (LONG_PTR)test_proc, proc);
1921 ddraw = create_ddraw();
1922 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1923 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1924 (LONG_PTR)test_proc, proc);
1925 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1926 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1927 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1928 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1929 (LONG_PTR)test_proc, proc);
1930 ref = IDirectDraw_Release(ddraw);
1931 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1932 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1933 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1934 (LONG_PTR)DefWindowProcA, proc);
1936 fix_wndproc(window, (LONG_PTR)test_proc);
1937 expect_messages = NULL;
1938 DestroyWindow(window);
1939 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
1942 static void test_window_style(void)
1944 LONG style, exstyle, tmp;
1945 RECT fullscreen_rect, r;
1946 IDirectDraw *ddraw;
1947 HWND window;
1948 HRESULT hr;
1949 ULONG ref;
1951 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1952 0, 0, 100, 100, 0, 0, 0, 0);
1953 ddraw = create_ddraw();
1954 ok(!!ddraw, "Failed to create a ddraw object.\n");
1956 style = GetWindowLongA(window, GWL_STYLE);
1957 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
1958 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
1960 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1961 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1963 tmp = GetWindowLongA(window, GWL_STYLE);
1964 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
1965 tmp = GetWindowLongA(window, GWL_EXSTYLE);
1966 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
1968 GetWindowRect(window, &r);
1969 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
1970 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
1971 r.left, r.top, r.right, r.bottom);
1972 GetClientRect(window, &r);
1973 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
1975 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1976 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1978 tmp = GetWindowLongA(window, GWL_STYLE);
1979 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
1980 tmp = GetWindowLongA(window, GWL_EXSTYLE);
1981 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
1983 ref = IDirectDraw_Release(ddraw);
1984 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1986 DestroyWindow(window);
1989 static void test_redundant_mode_set(void)
1991 DDSURFACEDESC surface_desc = {0};
1992 IDirectDraw *ddraw;
1993 HWND window;
1994 HRESULT hr;
1995 RECT r, s;
1996 ULONG ref;
1998 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1999 0, 0, 100, 100, 0, 0, 0, 0);
2000 ddraw = create_ddraw();
2001 ok(!!ddraw, "Failed to create a ddraw object.\n");
2003 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2004 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2006 surface_desc.dwSize = sizeof(surface_desc);
2007 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
2008 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
2010 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2011 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
2012 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2014 GetWindowRect(window, &r);
2015 r.right /= 2;
2016 r.bottom /= 2;
2017 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2018 GetWindowRect(window, &s);
2019 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2020 r.left, r.top, r.right, r.bottom,
2021 s.left, s.top, s.right, s.bottom);
2023 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2024 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
2025 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2027 GetWindowRect(window, &s);
2028 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2029 r.left, r.top, r.right, r.bottom,
2030 s.left, s.top, s.right, s.bottom);
2032 ref = IDirectDraw_Release(ddraw);
2033 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2035 DestroyWindow(window);
2038 static SIZE screen_size;
2040 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2042 if (message == WM_SIZE)
2044 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2045 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2048 return test_proc(hwnd, message, wparam, lparam);
2051 static void test_coop_level_mode_set(void)
2053 IDirectDrawSurface *primary;
2054 RECT fullscreen_rect, r, s;
2055 IDirectDraw *ddraw;
2056 DDSURFACEDESC ddsd;
2057 WNDCLASSA wc = {0};
2058 HWND window;
2059 HRESULT hr;
2060 ULONG ref;
2062 static const UINT exclusive_messages[] =
2064 WM_WINDOWPOSCHANGING,
2065 WM_WINDOWPOSCHANGED,
2066 WM_SIZE,
2067 WM_DISPLAYCHANGE,
2071 static const UINT normal_messages[] =
2073 WM_DISPLAYCHANGE,
2077 ddraw = create_ddraw();
2078 ok(!!ddraw, "Failed to create a ddraw object.\n");
2080 wc.lpfnWndProc = mode_set_proc;
2081 wc.lpszClassName = "ddraw_test_wndproc_wc";
2082 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2084 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2085 0, 0, 100, 100, 0, 0, 0, 0);
2087 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2088 SetRect(&s, 0, 0, 640, 480);
2090 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2091 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2093 GetWindowRect(window, &r);
2094 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2095 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2096 r.left, r.top, r.right, r.bottom);
2098 memset(&ddsd, 0, sizeof(ddsd));
2099 ddsd.dwSize = sizeof(ddsd);
2100 ddsd.dwFlags = DDSD_CAPS;
2101 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2103 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2104 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2105 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2106 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2107 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2108 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2109 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2110 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2112 GetWindowRect(window, &r);
2113 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2114 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2115 r.left, r.top, r.right, r.bottom);
2117 expect_messages = exclusive_messages;
2118 screen_size.cx = 0;
2119 screen_size.cy = 0;
2121 hr = set_display_mode(ddraw, 640, 480);
2122 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2124 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2125 expect_messages = NULL;
2126 ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
2127 "Expected screen size %ux%u, got %ux%u.\n",
2128 s.right, s.bottom, screen_size.cx, screen_size.cy);
2130 GetWindowRect(window, &r);
2131 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2132 s.left, s.top, s.right, s.bottom,
2133 r.left, r.top, r.right, r.bottom);
2135 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2136 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2137 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2138 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2139 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2140 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2141 IDirectDrawSurface_Release(primary);
2143 memset(&ddsd, 0, sizeof(ddsd));
2144 ddsd.dwSize = sizeof(ddsd);
2145 ddsd.dwFlags = DDSD_CAPS;
2146 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2148 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2149 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2150 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2151 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2152 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2153 s.right - s.left, ddsd.dwWidth);
2154 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2155 s.bottom - s.top, ddsd.dwHeight);
2157 GetWindowRect(window, &r);
2158 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2159 s.left, s.top, s.right, s.bottom,
2160 r.left, r.top, r.right, r.bottom);
2162 expect_messages = exclusive_messages;
2163 screen_size.cx = 0;
2164 screen_size.cy = 0;
2166 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2167 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2169 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2170 expect_messages = NULL;
2171 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2172 "Expected screen size %ux%u, got %ux%u.\n",
2173 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2175 GetWindowRect(window, &r);
2176 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2177 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2178 r.left, r.top, r.right, r.bottom);
2180 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2181 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2182 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2183 s.right - s.left, ddsd.dwWidth);
2184 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2185 s.bottom - s.top, ddsd.dwHeight);
2186 IDirectDrawSurface_Release(primary);
2188 memset(&ddsd, 0, sizeof(ddsd));
2189 ddsd.dwSize = sizeof(ddsd);
2190 ddsd.dwFlags = DDSD_CAPS;
2191 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2193 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2194 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2195 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2196 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2197 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2198 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2199 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2200 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2202 GetWindowRect(window, &r);
2203 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2204 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2205 r.left, r.top, r.right, r.bottom);
2207 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2208 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2210 GetWindowRect(window, &r);
2211 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2212 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2213 r.left, r.top, r.right, r.bottom);
2215 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2216 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2217 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2218 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2219 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2220 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2221 IDirectDrawSurface_Release(primary);
2223 memset(&ddsd, 0, sizeof(ddsd));
2224 ddsd.dwSize = sizeof(ddsd);
2225 ddsd.dwFlags = DDSD_CAPS;
2226 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2228 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2229 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2230 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2231 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2232 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2233 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2234 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2235 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2237 GetWindowRect(window, &r);
2238 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2239 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2240 r.left, r.top, r.right, r.bottom);
2242 expect_messages = normal_messages;
2243 screen_size.cx = 0;
2244 screen_size.cy = 0;
2246 hr = set_display_mode(ddraw, 640, 480);
2247 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
2249 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
2250 IDirectDrawSurface_Release(primary);
2251 IDirectDraw_Release(ddraw);
2252 goto done;
2254 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2256 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2257 expect_messages = NULL;
2258 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2260 GetWindowRect(window, &r);
2261 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2262 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2263 r.left, r.top, r.right, r.bottom);
2265 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2266 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2267 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2268 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2269 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2270 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2271 IDirectDrawSurface_Release(primary);
2273 memset(&ddsd, 0, sizeof(ddsd));
2274 ddsd.dwSize = sizeof(ddsd);
2275 ddsd.dwFlags = DDSD_CAPS;
2276 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2278 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2279 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2280 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2281 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2282 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2283 s.right - s.left, ddsd.dwWidth);
2284 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2285 s.bottom - s.top, ddsd.dwHeight);
2287 GetWindowRect(window, &r);
2288 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2289 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2290 r.left, r.top, r.right, r.bottom);
2292 expect_messages = normal_messages;
2293 screen_size.cx = 0;
2294 screen_size.cy = 0;
2296 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2297 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2299 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2300 expect_messages = NULL;
2301 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
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 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2309 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2310 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2311 s.right - s.left, ddsd.dwWidth);
2312 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2313 s.bottom - s.top, ddsd.dwHeight);
2314 IDirectDrawSurface_Release(primary);
2316 memset(&ddsd, 0, sizeof(ddsd));
2317 ddsd.dwSize = sizeof(ddsd);
2318 ddsd.dwFlags = DDSD_CAPS;
2319 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2321 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2322 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2323 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2324 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2325 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2326 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2327 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2328 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2330 GetWindowRect(window, &r);
2331 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2332 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2333 r.left, r.top, r.right, r.bottom);
2335 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2336 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2337 * not DDSCL_FULLSCREEN. */
2338 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2339 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2341 GetWindowRect(window, &r);
2342 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2343 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2344 r.left, r.top, r.right, r.bottom);
2346 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2347 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2348 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2349 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2350 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2351 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2352 IDirectDrawSurface_Release(primary);
2354 memset(&ddsd, 0, sizeof(ddsd));
2355 ddsd.dwSize = sizeof(ddsd);
2356 ddsd.dwFlags = DDSD_CAPS;
2357 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2359 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2360 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2361 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2362 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2363 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2364 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2365 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2366 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2368 GetWindowRect(window, &r);
2369 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2370 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2371 r.left, r.top, r.right, r.bottom);
2373 expect_messages = normal_messages;
2374 screen_size.cx = 0;
2375 screen_size.cy = 0;
2377 hr = set_display_mode(ddraw, 640, 480);
2378 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2380 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2381 expect_messages = NULL;
2382 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
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 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2390 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2391 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2392 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2393 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2394 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2395 IDirectDrawSurface_Release(primary);
2397 memset(&ddsd, 0, sizeof(ddsd));
2398 ddsd.dwSize = sizeof(ddsd);
2399 ddsd.dwFlags = DDSD_CAPS;
2400 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2402 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2403 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2404 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2405 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2406 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2407 s.right - s.left, ddsd.dwWidth);
2408 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2409 s.bottom - s.top, ddsd.dwHeight);
2411 GetWindowRect(window, &r);
2412 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2413 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2414 r.left, r.top, r.right, r.bottom);
2416 expect_messages = normal_messages;
2417 screen_size.cx = 0;
2418 screen_size.cy = 0;
2420 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2421 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2423 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2424 expect_messages = NULL;
2425 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
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 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2433 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2434 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2435 s.right - s.left, ddsd.dwWidth);
2436 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2437 s.bottom - s.top, ddsd.dwHeight);
2438 IDirectDrawSurface_Release(primary);
2440 memset(&ddsd, 0, sizeof(ddsd));
2441 ddsd.dwSize = sizeof(ddsd);
2442 ddsd.dwFlags = DDSD_CAPS;
2443 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2445 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2446 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2447 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2448 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2449 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2450 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2451 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2452 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2453 IDirectDrawSurface_Release(primary);
2455 GetWindowRect(window, &r);
2456 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2457 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2458 r.left, r.top, r.right, r.bottom);
2460 /* Unlike ddraw2-7, changing from EXCLUSIVE to NORMAL does not restore the resolution */
2461 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2462 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2463 hr = set_display_mode(ddraw, 640, 480);
2464 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2466 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2467 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2469 memset(&ddsd, 0, sizeof(ddsd));
2470 ddsd.dwSize = sizeof(ddsd);
2471 ddsd.dwFlags = DDSD_CAPS;
2472 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2474 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2475 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2476 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2477 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2478 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2479 s.right - s.left, ddsd.dwWidth);
2480 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2481 s.bottom - s.top, ddsd.dwHeight);
2482 IDirectDrawSurface_Release(primary);
2483 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2484 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2486 ref = IDirectDraw_Release(ddraw);
2487 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2489 GetWindowRect(window, &r);
2490 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2491 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2492 r.left, r.top, r.right, r.bottom);
2494 done:
2495 expect_messages = NULL;
2496 DestroyWindow(window);
2497 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2500 static void test_coop_level_mode_set_multi(void)
2502 IDirectDraw *ddraw1, *ddraw2;
2503 UINT orig_w, orig_h, w, h;
2504 HWND window;
2505 HRESULT hr;
2506 ULONG ref;
2508 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2509 0, 0, 100, 100, 0, 0, 0, 0);
2510 ddraw1 = create_ddraw();
2511 ok(!!ddraw1, "Failed to create a ddraw object.\n");
2513 orig_w = GetSystemMetrics(SM_CXSCREEN);
2514 orig_h = GetSystemMetrics(SM_CYSCREEN);
2516 /* With just a single ddraw object, the display mode is restored on
2517 * release. */
2518 hr = set_display_mode(ddraw1, 800, 600);
2519 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
2521 win_skip("Broken SetDisplayMode(), skipping test.\n");
2522 IDirectDraw_Release(ddraw1);
2523 DestroyWindow(window);
2524 return;
2526 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2527 w = GetSystemMetrics(SM_CXSCREEN);
2528 ok(w == 800, "Got unexpected screen width %u.\n", w);
2529 h = GetSystemMetrics(SM_CYSCREEN);
2530 ok(h == 600, "Got unexpected screen height %u.\n", h);
2532 ref = IDirectDraw_Release(ddraw1);
2533 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2534 w = GetSystemMetrics(SM_CXSCREEN);
2535 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2536 h = GetSystemMetrics(SM_CYSCREEN);
2537 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2539 /* When there are multiple ddraw objects, the display mode is restored to
2540 * the initial mode, before the first SetDisplayMode() call. */
2541 ddraw1 = create_ddraw();
2542 hr = set_display_mode(ddraw1, 800, 600);
2543 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2544 w = GetSystemMetrics(SM_CXSCREEN);
2545 ok(w == 800, "Got unexpected screen width %u.\n", w);
2546 h = GetSystemMetrics(SM_CYSCREEN);
2547 ok(h == 600, "Got unexpected screen height %u.\n", h);
2549 ddraw2 = create_ddraw();
2550 hr = set_display_mode(ddraw2, 640, 480);
2551 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2552 w = GetSystemMetrics(SM_CXSCREEN);
2553 ok(w == 640, "Got unexpected screen width %u.\n", w);
2554 h = GetSystemMetrics(SM_CYSCREEN);
2555 ok(h == 480, "Got unexpected screen height %u.\n", h);
2557 ref = IDirectDraw_Release(ddraw2);
2558 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2559 w = GetSystemMetrics(SM_CXSCREEN);
2560 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2561 h = GetSystemMetrics(SM_CYSCREEN);
2562 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2564 ref = IDirectDraw_Release(ddraw1);
2565 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2566 w = GetSystemMetrics(SM_CXSCREEN);
2567 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2568 h = GetSystemMetrics(SM_CYSCREEN);
2569 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2571 /* Regardless of release ordering. */
2572 ddraw1 = create_ddraw();
2573 hr = set_display_mode(ddraw1, 800, 600);
2574 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2575 w = GetSystemMetrics(SM_CXSCREEN);
2576 ok(w == 800, "Got unexpected screen width %u.\n", w);
2577 h = GetSystemMetrics(SM_CYSCREEN);
2578 ok(h == 600, "Got unexpected screen height %u.\n", h);
2580 ddraw2 = create_ddraw();
2581 hr = set_display_mode(ddraw2, 640, 480);
2582 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2583 w = GetSystemMetrics(SM_CXSCREEN);
2584 ok(w == 640, "Got unexpected screen width %u.\n", w);
2585 h = GetSystemMetrics(SM_CYSCREEN);
2586 ok(h == 480, "Got unexpected screen height %u.\n", h);
2588 ref = IDirectDraw_Release(ddraw1);
2589 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2590 w = GetSystemMetrics(SM_CXSCREEN);
2591 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2592 h = GetSystemMetrics(SM_CYSCREEN);
2593 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2595 ref = IDirectDraw_Release(ddraw2);
2596 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2597 w = GetSystemMetrics(SM_CXSCREEN);
2598 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2599 h = GetSystemMetrics(SM_CYSCREEN);
2600 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2602 /* But only for ddraw objects that called SetDisplayMode(). */
2603 ddraw1 = create_ddraw();
2604 ddraw2 = create_ddraw();
2605 hr = set_display_mode(ddraw2, 640, 480);
2606 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2607 w = GetSystemMetrics(SM_CXSCREEN);
2608 ok(w == 640, "Got unexpected screen width %u.\n", w);
2609 h = GetSystemMetrics(SM_CYSCREEN);
2610 ok(h == 480, "Got unexpected screen height %u.\n", h);
2612 ref = IDirectDraw_Release(ddraw1);
2613 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2614 w = GetSystemMetrics(SM_CXSCREEN);
2615 ok(w == 640, "Got unexpected screen width %u.\n", w);
2616 h = GetSystemMetrics(SM_CYSCREEN);
2617 ok(h == 480, "Got unexpected screen height %u.\n", h);
2619 ref = IDirectDraw_Release(ddraw2);
2620 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2621 w = GetSystemMetrics(SM_CXSCREEN);
2622 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2623 h = GetSystemMetrics(SM_CYSCREEN);
2624 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2626 /* If there's a ddraw object that's currently in exclusive mode, it blocks
2627 * restoring the display mode. */
2628 ddraw1 = create_ddraw();
2629 hr = set_display_mode(ddraw1, 800, 600);
2630 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2631 w = GetSystemMetrics(SM_CXSCREEN);
2632 ok(w == 800, "Got unexpected screen width %u.\n", w);
2633 h = GetSystemMetrics(SM_CYSCREEN);
2634 ok(h == 600, "Got unexpected screen height %u.\n", h);
2636 ddraw2 = create_ddraw();
2637 hr = set_display_mode(ddraw2, 640, 480);
2638 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2639 w = GetSystemMetrics(SM_CXSCREEN);
2640 ok(w == 640, "Got unexpected screen width %u.\n", w);
2641 h = GetSystemMetrics(SM_CYSCREEN);
2642 ok(h == 480, "Got unexpected screen height %u.\n", h);
2644 hr = IDirectDraw_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2645 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2647 ref = IDirectDraw_Release(ddraw1);
2648 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2649 w = GetSystemMetrics(SM_CXSCREEN);
2650 ok(w == 640, "Got unexpected screen width %u.\n", w);
2651 h = GetSystemMetrics(SM_CYSCREEN);
2652 ok(h == 480, "Got unexpected screen height %u.\n", h);
2654 ref = IDirectDraw_Release(ddraw2);
2655 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2656 w = GetSystemMetrics(SM_CXSCREEN);
2657 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2658 h = GetSystemMetrics(SM_CYSCREEN);
2659 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2661 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
2662 ddraw1 = create_ddraw();
2663 hr = set_display_mode(ddraw1, 800, 600);
2664 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2665 w = GetSystemMetrics(SM_CXSCREEN);
2666 ok(w == 800, "Got unexpected screen width %u.\n", w);
2667 h = GetSystemMetrics(SM_CYSCREEN);
2668 ok(h == 600, "Got unexpected screen height %u.\n", h);
2670 hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2671 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2673 ddraw2 = create_ddraw();
2674 hr = set_display_mode(ddraw2, 640, 480);
2675 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
2677 ref = IDirectDraw_Release(ddraw1);
2678 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2679 w = GetSystemMetrics(SM_CXSCREEN);
2680 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2681 h = GetSystemMetrics(SM_CYSCREEN);
2682 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2684 ref = IDirectDraw_Release(ddraw2);
2685 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2686 w = GetSystemMetrics(SM_CXSCREEN);
2687 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2688 h = GetSystemMetrics(SM_CYSCREEN);
2689 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2691 DestroyWindow(window);
2694 static void test_initialize(void)
2696 IDirectDraw *ddraw;
2697 IDirect3D *d3d;
2698 HRESULT hr;
2700 ddraw = create_ddraw();
2701 ok(!!ddraw, "Failed to create a ddraw object.\n");
2703 hr = IDirectDraw_Initialize(ddraw, NULL);
2704 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
2705 IDirectDraw_Release(ddraw);
2707 CoInitialize(NULL);
2708 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw);
2709 ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
2710 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
2711 if (SUCCEEDED(hr))
2713 /* IDirect3D_Initialize() just returns DDERR_ALREADYINITIALIZED. */
2714 hr = IDirect3D_Initialize(d3d, NULL);
2715 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2716 IDirect3D_Release(d3d);
2718 else
2719 skip("D3D interface is not available, skipping test.\n");
2720 hr = IDirectDraw_Initialize(ddraw, NULL);
2721 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
2722 hr = IDirectDraw_Initialize(ddraw, NULL);
2723 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2724 IDirectDraw_Release(ddraw);
2725 CoUninitialize();
2727 if (0) /* This crashes on the W2KPROSP4 testbot. */
2729 CoInitialize(NULL);
2730 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d);
2731 ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#x, expected E_NOINTERFACE.\n", hr);
2732 CoUninitialize();
2736 static void test_coop_level_surf_create(void)
2738 IDirectDrawSurface *surface;
2739 IDirectDraw *ddraw;
2740 DDSURFACEDESC ddsd;
2741 HRESULT hr;
2743 ddraw = create_ddraw();
2744 ok(!!ddraw, "Failed to create a ddraw object.\n");
2746 memset(&ddsd, 0, sizeof(ddsd));
2747 ddsd.dwSize = sizeof(ddsd);
2748 ddsd.dwFlags = DDSD_CAPS;
2749 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2750 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
2751 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
2753 IDirectDraw_Release(ddraw);
2756 static void test_coop_level_multi_window(void)
2758 HWND window1, window2;
2759 IDirectDraw *ddraw;
2760 HRESULT hr;
2762 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
2763 0, 0, 640, 480, 0, 0, 0, 0);
2764 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
2765 0, 0, 640, 480, 0, 0, 0, 0);
2766 ddraw = create_ddraw();
2767 ok(!!ddraw, "Failed to create a ddraw object.\n");
2769 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
2770 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2771 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
2772 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2773 ok(IsWindow(window1), "Window 1 was destroyed.\n");
2774 ok(IsWindow(window2), "Window 2 was destroyed.\n");
2776 IDirectDraw_Release(ddraw);
2777 DestroyWindow(window2);
2778 DestroyWindow(window1);
2781 static void test_clear_rect_count(void)
2783 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
2784 IDirect3DMaterial *white, *red, *green, *blue;
2785 IDirect3DViewport *viewport;
2786 IDirect3DDevice *device;
2787 IDirectDrawSurface *rt;
2788 IDirectDraw *ddraw;
2789 D3DCOLOR color;
2790 HWND window;
2791 HRESULT hr;
2793 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2794 0, 0, 640, 480, 0, 0, 0, 0);
2795 ddraw = create_ddraw();
2796 ok(!!ddraw, "Failed to create a ddraw object.\n");
2797 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2799 skip("Failed to create a 3D device, skipping test.\n");
2800 IDirectDraw_Release(ddraw);
2801 DestroyWindow(window);
2802 return;
2805 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
2806 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
2808 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
2809 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
2810 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
2811 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
2812 viewport = create_viewport(device, 0, 0, 640, 480);
2814 viewport_set_background(device, viewport, white);
2815 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2816 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2817 viewport_set_background(device, viewport, red);
2818 hr = IDirect3DViewport_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
2819 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2820 viewport_set_background(device, viewport, green);
2821 hr = IDirect3DViewport_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
2822 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2823 viewport_set_background(device, viewport, blue);
2824 hr = IDirect3DViewport_Clear(viewport, 1, NULL, D3DCLEAR_TARGET);
2825 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2827 color = get_surface_color(rt, 320, 240);
2828 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
2830 IDirectDrawSurface_Release(rt);
2831 destroy_viewport(device, viewport);
2832 destroy_material(white);
2833 destroy_material(red);
2834 destroy_material(green);
2835 destroy_material(blue);
2836 IDirect3DDevice_Release(device);
2837 IDirectDraw_Release(ddraw);
2838 DestroyWindow(window);
2841 static struct
2843 BOOL received;
2844 IDirectDraw *ddraw;
2845 HWND window;
2846 DWORD coop_level;
2847 } activateapp_testdata;
2849 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2851 if (message == WM_ACTIVATEAPP)
2853 if (activateapp_testdata.ddraw)
2855 HRESULT hr;
2856 activateapp_testdata.received = FALSE;
2857 hr = IDirectDraw_SetCooperativeLevel(activateapp_testdata.ddraw,
2858 activateapp_testdata.window, activateapp_testdata.coop_level);
2859 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
2860 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
2862 activateapp_testdata.received = TRUE;
2865 return DefWindowProcA(hwnd, message, wparam, lparam);
2868 static void test_coop_level_activateapp(void)
2870 IDirectDraw *ddraw;
2871 HRESULT hr;
2872 HWND window;
2873 WNDCLASSA wc = {0};
2874 DDSURFACEDESC ddsd;
2875 IDirectDrawSurface *surface;
2877 ddraw = create_ddraw();
2878 ok(!!ddraw, "Failed to create a ddraw object.\n");
2880 wc.lpfnWndProc = activateapp_test_proc;
2881 wc.lpszClassName = "ddraw_test_wndproc_wc";
2882 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2884 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2885 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2887 /* Exclusive with window already active. */
2888 SetActiveWindow(window);
2889 activateapp_testdata.received = FALSE;
2890 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2891 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2892 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
2893 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2894 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2896 /* Exclusive with window not active. */
2897 SetActiveWindow(NULL);
2898 activateapp_testdata.received = FALSE;
2899 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2900 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2901 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
2902 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2903 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2905 /* Normal with window not active, then exclusive with the same window. */
2906 SetActiveWindow(NULL);
2907 activateapp_testdata.received = FALSE;
2908 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2909 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2910 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
2911 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2912 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2913 /* Except in the first SetCooperativeLevel call, Windows XP randomly does not send
2914 * WM_ACTIVATEAPP. Windows 7 sends the message reliably. Mark the XP behavior broken. */
2915 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
2916 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
2917 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2918 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2920 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
2921 SetActiveWindow(NULL);
2922 activateapp_testdata.received = FALSE;
2923 activateapp_testdata.ddraw = ddraw;
2924 activateapp_testdata.window = window;
2925 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
2926 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2927 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2928 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
2929 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
2930 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2931 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2933 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
2934 * succeeding. Another switch to exclusive and back to normal is needed to release the
2935 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
2936 * WM_ACTIVATEAPP messages. */
2937 activateapp_testdata.ddraw = NULL;
2938 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2939 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2940 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2941 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2943 /* Setting DDSCL_NORMAL with recursive invocation. */
2944 SetActiveWindow(NULL);
2945 activateapp_testdata.received = FALSE;
2946 activateapp_testdata.ddraw = ddraw;
2947 activateapp_testdata.window = window;
2948 activateapp_testdata.coop_level = DDSCL_NORMAL;
2949 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2950 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2951 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
2952 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
2954 /* DDraw is in exlusive mode now. */
2955 memset(&ddsd, 0, sizeof(ddsd));
2956 ddsd.dwSize = sizeof(ddsd);
2957 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
2958 ddsd.dwBackBufferCount = 1;
2959 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
2960 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
2961 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2962 IDirectDrawSurface_Release(surface);
2964 /* Recover again, just to be sure. */
2965 activateapp_testdata.ddraw = NULL;
2966 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2967 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2968 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2969 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2971 DestroyWindow(window);
2972 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2973 IDirectDraw_Release(ddraw);
2976 struct format_support_check
2978 const DDPIXELFORMAT *format;
2979 BOOL supported;
2982 static HRESULT WINAPI test_unsupported_formats_cb(DDSURFACEDESC *desc, void *ctx)
2984 struct format_support_check *format = ctx;
2986 if (!memcmp(format->format, &desc->ddpfPixelFormat, sizeof(*format->format)))
2988 format->supported = TRUE;
2989 return DDENUMRET_CANCEL;
2992 return DDENUMRET_OK;
2995 static void test_unsupported_formats(void)
2997 HRESULT hr;
2998 BOOL expect_success;
2999 HWND window;
3000 IDirectDraw *ddraw;
3001 IDirect3DDevice *device;
3002 IDirectDrawSurface *surface;
3003 DDSURFACEDESC ddsd;
3004 unsigned int i, j;
3005 DWORD expected_caps;
3006 static const struct
3008 const char *name;
3009 DDPIXELFORMAT fmt;
3011 formats[] =
3014 "D3DFMT_A8R8G8B8",
3016 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3017 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
3021 "D3DFMT_P8",
3023 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3024 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3028 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
3030 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3031 0, 0, 640, 480, 0, 0, 0, 0);
3032 ddraw = create_ddraw();
3033 ok(!!ddraw, "Failed to create a ddraw object.\n");
3034 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3036 skip("Failed to create a 3D device, skipping test.\n");
3037 IDirectDraw_Release(ddraw);
3038 DestroyWindow(window);
3039 return;
3042 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
3044 struct format_support_check check = {&formats[i].fmt, FALSE};
3045 hr = IDirect3DDevice_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
3046 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
3048 for (j = 0; j < sizeof(caps) / sizeof(*caps); j++)
3050 memset(&ddsd, 0, sizeof(ddsd));
3051 ddsd.dwSize = sizeof(ddsd);
3052 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3053 ddsd.ddpfPixelFormat = formats[i].fmt;
3054 ddsd.dwWidth = 4;
3055 ddsd.dwHeight = 4;
3056 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
3058 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
3059 expect_success = FALSE;
3060 else
3061 expect_success = TRUE;
3063 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3064 ok(SUCCEEDED(hr) == expect_success,
3065 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
3066 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
3067 if (FAILED(hr))
3068 continue;
3070 memset(&ddsd, 0, sizeof(ddsd));
3071 ddsd.dwSize = sizeof(ddsd);
3072 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
3073 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3075 if (caps[j] & DDSCAPS_VIDEOMEMORY)
3076 expected_caps = DDSCAPS_VIDEOMEMORY;
3077 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
3078 expected_caps = DDSCAPS_SYSTEMMEMORY;
3079 else if (check.supported)
3080 expected_caps = DDSCAPS_VIDEOMEMORY;
3081 else
3082 expected_caps = DDSCAPS_SYSTEMMEMORY;
3084 ok(ddsd.ddsCaps.dwCaps & expected_caps,
3085 "Expected capability %#x, format %s, input cap %#x.\n",
3086 expected_caps, formats[i].name, caps[j]);
3088 IDirectDrawSurface_Release(surface);
3092 IDirect3DDevice_Release(device);
3093 IDirectDraw_Release(ddraw);
3094 DestroyWindow(window);
3097 static void test_rt_caps(void)
3099 PALETTEENTRY palette_entries[256];
3100 IDirectDrawPalette *palette;
3101 IDirect3DDevice *device;
3102 IDirectDraw *ddraw;
3103 DWORD z_depth = 0;
3104 unsigned int i;
3105 ULONG refcount;
3106 HWND window;
3107 HRESULT hr;
3109 static const DDPIXELFORMAT p8_fmt =
3111 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3112 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
3115 static const struct
3117 const DDPIXELFORMAT *pf;
3118 DWORD caps_in;
3119 DWORD caps_out;
3120 HRESULT create_device_hr;
3121 BOOL create_may_fail;
3123 test_data[] =
3126 NULL,
3127 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3128 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3129 D3D_OK,
3130 FALSE,
3133 NULL,
3134 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3135 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3136 D3D_OK,
3137 FALSE,
3140 NULL,
3141 DDSCAPS_OFFSCREENPLAIN,
3142 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3143 DDERR_INVALIDCAPS,
3144 FALSE,
3147 NULL,
3148 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3149 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3150 D3DERR_SURFACENOTINVIDMEM,
3151 FALSE,
3154 NULL,
3155 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3156 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3157 DDERR_INVALIDCAPS,
3158 FALSE,
3161 NULL,
3162 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3163 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3164 D3D_OK,
3165 FALSE,
3168 NULL,
3169 DDSCAPS_3DDEVICE,
3170 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3171 D3D_OK,
3172 FALSE,
3175 NULL,
3177 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3178 DDERR_INVALIDCAPS,
3179 FALSE,
3182 NULL,
3183 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3184 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3185 D3DERR_SURFACENOTINVIDMEM,
3186 FALSE,
3189 NULL,
3190 DDSCAPS_SYSTEMMEMORY,
3191 DDSCAPS_SYSTEMMEMORY,
3192 DDERR_INVALIDCAPS,
3193 FALSE,
3196 &p8_fmt,
3198 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3199 DDERR_INVALIDCAPS,
3200 FALSE,
3203 &p8_fmt,
3204 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3205 ~0U /* AMD r200 */ ,
3206 DDERR_NOPALETTEATTACHED,
3207 FALSE,
3210 &p8_fmt,
3211 DDSCAPS_OFFSCREENPLAIN,
3212 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3213 DDERR_INVALIDCAPS,
3214 FALSE,
3217 &p8_fmt,
3218 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3219 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3220 DDERR_NOPALETTEATTACHED,
3221 FALSE,
3224 &p8_fmt,
3225 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3226 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3227 DDERR_INVALIDCAPS,
3228 FALSE,
3231 NULL,
3232 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
3233 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
3234 DDERR_INVALIDCAPS,
3235 TRUE /* AMD Evergreen */,
3238 NULL,
3239 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3240 ~0U /* AMD Evergreen */,
3241 DDERR_INVALIDCAPS,
3242 FALSE,
3245 NULL,
3246 DDSCAPS_ZBUFFER,
3247 ~0U /* AMD Evergreen */,
3248 DDERR_INVALIDCAPS,
3249 FALSE,
3252 NULL,
3253 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3254 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3255 DDERR_INVALIDCAPS,
3256 TRUE /* Nvidia Kepler */,
3259 NULL,
3260 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3261 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3262 DDERR_INVALIDCAPS,
3263 TRUE /* Nvidia Kepler */,
3267 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3268 0, 0, 640, 480, 0, 0, 0, 0);
3269 ddraw = create_ddraw();
3270 ok(!!ddraw, "Failed to create a ddraw object.\n");
3271 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3273 skip("Failed to create a 3D device, skipping test.\n");
3274 IDirectDraw_Release(ddraw);
3275 DestroyWindow(window);
3276 return;
3278 z_depth = get_device_z_depth(device);
3279 ok(!!z_depth, "Failed to get device z depth.\n");
3280 IDirect3DDevice_Release(device);
3282 memset(palette_entries, 0, sizeof(palette_entries));
3283 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
3284 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
3286 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
3288 IDirectDrawSurface *surface;
3289 DDSURFACEDESC surface_desc;
3290 IDirect3DDevice *device;
3292 memset(&surface_desc, 0, sizeof(surface_desc));
3293 surface_desc.dwSize = sizeof(surface_desc);
3294 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3295 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
3296 if (test_data[i].pf)
3298 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
3299 surface_desc.ddpfPixelFormat = *test_data[i].pf;
3301 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
3303 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
3304 U2(surface_desc).dwZBufferBitDepth = z_depth;
3306 surface_desc.dwWidth = 640;
3307 surface_desc.dwHeight = 480;
3308 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3309 ok(SUCCEEDED(hr) || broken(test_data[i].create_may_fail),
3310 "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
3311 i, test_data[i].caps_in, hr);
3312 if (FAILED(hr))
3313 continue;
3315 memset(&surface_desc, 0, sizeof(surface_desc));
3316 surface_desc.dwSize = sizeof(surface_desc);
3317 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
3318 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
3319 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
3320 "Test %u: Got unexpected caps %#x, expected %#x.\n",
3321 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
3323 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
3324 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
3325 i, hr, test_data[i].create_device_hr);
3326 if (hr == DDERR_NOPALETTEATTACHED)
3328 hr = IDirectDrawSurface_SetPalette(surface, palette);
3329 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
3330 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
3331 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
3332 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
3333 else
3334 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
3336 if (SUCCEEDED(hr))
3338 refcount = IDirect3DDevice_Release(device);
3339 ok(refcount == 1, "Test %u: Got unexpected refcount %u.\n", i, refcount);
3342 refcount = IDirectDrawSurface_Release(surface);
3343 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
3346 IDirectDrawPalette_Release(palette);
3347 refcount = IDirectDraw_Release(ddraw);
3348 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3349 DestroyWindow(window);
3352 static void test_primary_caps(void)
3354 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
3355 IDirectDrawSurface *surface;
3356 DDSURFACEDESC surface_desc;
3357 IDirectDraw *ddraw;
3358 unsigned int i;
3359 ULONG refcount;
3360 HWND window;
3361 HRESULT hr;
3363 static const struct
3365 DWORD coop_level;
3366 DWORD caps_in;
3367 DWORD back_buffer_count;
3368 HRESULT hr;
3369 DWORD caps_out;
3371 test_data[] =
3374 DDSCL_NORMAL,
3375 DDSCAPS_PRIMARYSURFACE,
3376 ~0u,
3377 DD_OK,
3378 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
3381 DDSCL_NORMAL,
3382 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
3383 ~0u,
3384 DDERR_INVALIDCAPS,
3385 ~0u,
3388 DDSCL_NORMAL,
3389 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
3390 ~0u,
3391 DD_OK,
3392 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
3395 DDSCL_NORMAL,
3396 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
3397 ~0u,
3398 DDERR_INVALIDCAPS,
3399 ~0u,
3402 DDSCL_NORMAL,
3403 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
3404 ~0u,
3405 DDERR_INVALIDCAPS,
3406 ~0u,
3409 DDSCL_NORMAL,
3410 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
3411 ~0u,
3412 DDERR_INVALIDCAPS,
3413 ~0u,
3416 DDSCL_NORMAL,
3417 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3418 ~0u,
3419 DDERR_INVALIDCAPS,
3420 ~0u,
3423 DDSCL_NORMAL,
3424 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3426 DDERR_INVALIDCAPS,
3427 ~0u,
3430 DDSCL_NORMAL,
3431 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3433 DDERR_NOEXCLUSIVEMODE,
3434 ~0u,
3437 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3438 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3440 DDERR_INVALIDCAPS,
3441 ~0u,
3444 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3445 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3447 DD_OK,
3448 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
3451 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3452 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
3454 DDERR_INVALIDCAPS,
3455 ~0u,
3458 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3459 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
3461 DDERR_INVALIDCAPS,
3462 ~0u,
3466 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3467 0, 0, 640, 480, 0, 0, 0, 0);
3468 ddraw = create_ddraw();
3469 ok(!!ddraw, "Failed to create a ddraw object.\n");
3471 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
3473 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
3474 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3476 memset(&surface_desc, 0, sizeof(surface_desc));
3477 surface_desc.dwSize = sizeof(surface_desc);
3478 surface_desc.dwFlags = DDSD_CAPS;
3479 if (test_data[i].back_buffer_count != ~0u)
3480 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
3481 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
3482 surface_desc.dwBackBufferCount = test_data[i].back_buffer_count;
3483 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3484 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
3485 if (FAILED(hr))
3486 continue;
3488 memset(&surface_desc, 0, sizeof(surface_desc));
3489 surface_desc.dwSize = sizeof(surface_desc);
3490 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
3491 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
3492 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
3493 "Test %u: Got unexpected caps %#x, expected %#x.\n",
3494 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
3496 IDirectDrawSurface_Release(surface);
3499 refcount = IDirectDraw_Release(ddraw);
3500 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3501 DestroyWindow(window);
3504 static void test_surface_lock(void)
3506 IDirectDraw *ddraw;
3507 IDirectDrawSurface *surface;
3508 IDirect3DDevice *device;
3509 HRESULT hr;
3510 HWND window;
3511 unsigned int i;
3512 DDSURFACEDESC ddsd;
3513 ULONG refcount;
3514 DWORD z_depth = 0;
3515 static const struct
3517 DWORD caps;
3518 const char *name;
3520 tests[] =
3523 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
3524 "videomemory offscreenplain"
3527 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3528 "systemmemory offscreenplain"
3531 DDSCAPS_PRIMARYSURFACE,
3532 "primary"
3535 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
3536 "videomemory texture"
3539 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
3540 "systemmemory texture"
3543 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3544 "render target"
3547 DDSCAPS_ZBUFFER,
3548 "Z buffer"
3552 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3553 0, 0, 640, 480, 0, 0, 0, 0);
3554 ddraw = create_ddraw();
3555 ok(!!ddraw, "Failed to create a ddraw object.\n");
3556 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3558 skip("Failed to create a 3D device, skipping test.\n");
3559 IDirectDraw_Release(ddraw);
3560 DestroyWindow(window);
3561 return;
3563 z_depth = get_device_z_depth(device);
3564 ok(!!z_depth, "Failed to get device z depth.\n");
3565 IDirect3DDevice_Release(device);
3567 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
3569 memset(&ddsd, 0, sizeof(ddsd));
3570 ddsd.dwSize = sizeof(ddsd);
3571 ddsd.dwFlags = DDSD_CAPS;
3572 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
3574 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
3575 ddsd.dwWidth = 64;
3576 ddsd.dwHeight = 64;
3578 if (tests[i].caps & DDSCAPS_ZBUFFER)
3580 ddsd.dwFlags |= DDSD_ZBUFFERBITDEPTH;
3581 U2(ddsd).dwZBufferBitDepth = z_depth;
3583 ddsd.ddsCaps.dwCaps = tests[i].caps;
3585 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3586 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
3588 memset(&ddsd, 0, sizeof(ddsd));
3589 ddsd.dwSize = sizeof(ddsd);
3590 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
3591 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
3592 if (SUCCEEDED(hr))
3594 hr = IDirectDrawSurface_Unlock(surface, NULL);
3595 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
3598 IDirectDrawSurface_Release(surface);
3601 refcount = IDirectDraw_Release(ddraw);
3602 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3603 DestroyWindow(window);
3606 static void test_surface_discard(void)
3608 IDirectDraw *ddraw;
3609 HRESULT hr;
3610 HWND window;
3611 DDSURFACEDESC ddsd;
3612 IDirectDrawSurface *surface, *primary;
3613 void *addr;
3614 static const struct
3616 DWORD caps;
3617 BOOL discard;
3619 tests[] =
3621 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, TRUE},
3622 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, FALSE},
3623 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, TRUE},
3624 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, FALSE},
3626 unsigned int i;
3628 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3629 0, 0, 640, 480, 0, 0, 0, 0);
3630 ddraw = create_ddraw();
3631 ok(!!ddraw, "Failed to create a ddraw object.\n");
3632 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3633 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3635 memset(&ddsd, 0, sizeof(ddsd));
3636 ddsd.dwSize = sizeof(ddsd);
3637 ddsd.dwFlags = DDSD_CAPS;
3638 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3639 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3641 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
3643 BOOL discarded;
3645 memset(&ddsd, 0, sizeof(ddsd));
3646 ddsd.dwSize = sizeof(ddsd);
3647 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3648 ddsd.ddsCaps.dwCaps = tests[i].caps;
3649 ddsd.dwWidth = 64;
3650 ddsd.dwHeight = 64;
3651 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3652 if (FAILED(hr))
3654 skip("Failed to create surface, skipping.\n");
3655 continue;
3658 memset(&ddsd, 0, sizeof(ddsd));
3659 ddsd.dwSize = sizeof(ddsd);
3660 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
3661 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
3662 addr = ddsd.lpSurface;
3663 hr = IDirectDrawSurface_Unlock(surface, NULL);
3664 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
3666 memset(&ddsd, 0, sizeof(ddsd));
3667 ddsd.dwSize = sizeof(ddsd);
3668 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
3669 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
3670 discarded = ddsd.lpSurface != addr;
3671 hr = IDirectDrawSurface_Unlock(surface, NULL);
3672 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
3674 hr = IDirectDrawSurface_Blt(primary, NULL, surface, NULL, DDBLT_WAIT, NULL);
3675 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
3677 memset(&ddsd, 0, sizeof(ddsd));
3678 ddsd.dwSize = sizeof(ddsd);
3679 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
3680 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
3681 discarded |= ddsd.lpSurface != addr;
3682 hr = IDirectDrawSurface_Unlock(surface, NULL);
3683 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
3685 IDirectDrawSurface_Release(surface);
3687 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
3688 * AMD r500, evergreen). Windows XP, at least on AMD r200, never changes the pointer. */
3689 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
3692 IDirectDrawSurface_Release(primary);
3693 IDirectDraw_Release(ddraw);
3694 DestroyWindow(window);
3697 static void test_flip(void)
3699 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
3700 IDirectDrawSurface *primary, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
3701 DDSCAPS caps = {DDSCAPS_FLIP};
3702 DDSURFACEDESC surface_desc;
3703 BOOL sysmem_primary;
3704 IDirectDraw *ddraw;
3705 D3DCOLOR color;
3706 ULONG refcount;
3707 HWND window;
3708 DDBLTFX fx;
3709 HRESULT hr;
3711 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3712 0, 0, 640, 480, 0, 0, 0, 0);
3713 ddraw = create_ddraw();
3714 ok(!!ddraw, "Failed to create a ddraw object.\n");
3716 hr = set_display_mode(ddraw, 640, 480);
3717 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3718 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3719 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3721 memset(&surface_desc, 0, sizeof(surface_desc));
3722 surface_desc.dwSize = sizeof(surface_desc);
3723 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
3724 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
3725 surface_desc.dwBackBufferCount = 3;
3726 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
3727 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3729 memset(&surface_desc, 0, sizeof(surface_desc));
3730 surface_desc.dwSize = sizeof(surface_desc);
3731 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
3732 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3733 ok((surface_desc.ddsCaps.dwCaps & ~placement)
3734 == (DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX),
3735 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3736 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
3738 hr = IDirectDrawSurface_GetAttachedSurface(primary, &caps, &backbuffer1);
3739 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3740 memset(&surface_desc, 0, sizeof(surface_desc));
3741 surface_desc.dwSize = sizeof(surface_desc);
3742 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer1, &surface_desc);
3743 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3744 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
3745 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_BACKBUFFER),
3746 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3748 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
3749 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3750 memset(&surface_desc, 0, sizeof(surface_desc));
3751 surface_desc.dwSize = sizeof(surface_desc);
3752 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer2, &surface_desc);
3753 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3754 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
3755 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
3756 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3758 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
3759 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3760 memset(&surface_desc, 0, sizeof(surface_desc));
3761 surface_desc.dwSize = sizeof(surface_desc);
3762 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer3, &surface_desc);
3763 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3764 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
3765 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
3766 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3768 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer3, &caps, &surface);
3769 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3770 ok(surface == primary, "Got unexpected surface %p, expected %p.\n", surface, primary);
3771 IDirectDrawSurface_Release(surface);
3773 memset(&surface_desc, 0, sizeof(surface_desc));
3774 surface_desc.dwSize = sizeof(surface_desc);
3775 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3776 surface_desc.ddsCaps.dwCaps = 0;
3777 surface_desc.dwWidth = 640;
3778 surface_desc.dwHeight = 480;
3779 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3780 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3781 hr = IDirectDrawSurface_Flip(primary, surface, DDFLIP_WAIT);
3782 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3783 IDirectDrawSurface_Release(surface);
3785 hr = IDirectDrawSurface_Flip(primary, primary, DDFLIP_WAIT);
3786 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3787 hr = IDirectDrawSurface_Flip(backbuffer1, NULL, DDFLIP_WAIT);
3788 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3789 hr = IDirectDrawSurface_Flip(backbuffer2, NULL, DDFLIP_WAIT);
3790 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3791 hr = IDirectDrawSurface_Flip(backbuffer3, NULL, DDFLIP_WAIT);
3792 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3794 memset(&fx, 0, sizeof(fx));
3795 fx.dwSize = sizeof(fx);
3796 U5(fx).dwFillColor = 0xffff0000;
3797 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3798 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3799 U5(fx).dwFillColor = 0xff00ff00;
3800 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3801 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3802 U5(fx).dwFillColor = 0xff0000ff;
3803 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3804 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3806 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
3807 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3808 color = get_surface_color(backbuffer1, 320, 240);
3809 /* The testbot seems to just copy the contents of one surface to all the
3810 * others, instead of properly flipping. */
3811 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
3812 "Got unexpected color 0x%08x.\n", color);
3813 color = get_surface_color(backbuffer2, 320, 240);
3814 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
3815 U5(fx).dwFillColor = 0xffff0000;
3816 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3817 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3819 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
3820 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3821 color = get_surface_color(backbuffer1, 320, 240);
3822 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
3823 "Got unexpected color 0x%08x.\n", color);
3824 color = get_surface_color(backbuffer2, 320, 240);
3825 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
3826 U5(fx).dwFillColor = 0xff00ff00;
3827 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3828 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3830 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
3831 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3832 color = get_surface_color(backbuffer1, 320, 240);
3833 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
3834 "Got unexpected color 0x%08x.\n", color);
3835 color = get_surface_color(backbuffer2, 320, 240);
3836 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3837 U5(fx).dwFillColor = 0xff0000ff;
3838 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3839 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3841 hr = IDirectDrawSurface_Flip(primary, backbuffer1, DDFLIP_WAIT);
3842 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3843 color = get_surface_color(backbuffer2, 320, 240);
3844 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
3845 "Got unexpected color 0x%08x.\n", color);
3846 color = get_surface_color(backbuffer3, 320, 240);
3847 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
3848 U5(fx).dwFillColor = 0xffff0000;
3849 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3850 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3852 hr = IDirectDrawSurface_Flip(primary, backbuffer2, DDFLIP_WAIT);
3853 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3854 color = get_surface_color(backbuffer1, 320, 240);
3855 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
3856 color = get_surface_color(backbuffer3, 320, 240);
3857 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
3858 "Got unexpected color 0x%08x.\n", color);
3859 U5(fx).dwFillColor = 0xff00ff00;
3860 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3861 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3863 hr = IDirectDrawSurface_Flip(primary, backbuffer3, DDFLIP_WAIT);
3864 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3865 color = get_surface_color(backbuffer1, 320, 240);
3866 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
3867 "Got unexpected color 0x%08x.\n", color);
3868 color = get_surface_color(backbuffer2, 320, 240);
3869 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3871 IDirectDrawSurface_Release(backbuffer3);
3872 IDirectDrawSurface_Release(backbuffer2);
3873 IDirectDrawSurface_Release(backbuffer1);
3874 IDirectDrawSurface_Release(primary);
3875 refcount = IDirectDraw_Release(ddraw);
3876 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3877 DestroyWindow(window);
3880 static void test_sysmem_overlay(void)
3882 IDirectDraw *ddraw;
3883 HWND window;
3884 HRESULT hr;
3885 DDSURFACEDESC ddsd;
3886 IDirectDrawSurface *surface;
3887 ULONG ref;
3889 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3890 0, 0, 640, 480, 0, 0, 0, 0);
3891 ddraw = create_ddraw();
3892 ok(!!ddraw, "Failed to create a ddraw object.\n");
3894 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3895 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3897 memset(&ddsd, 0, sizeof(ddsd));
3898 ddsd.dwSize = sizeof(ddsd);
3899 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
3900 ddsd.dwWidth = 16;
3901 ddsd.dwHeight = 16;
3902 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
3903 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
3904 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
3905 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
3906 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
3907 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
3908 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
3909 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3910 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
3912 ref = IDirectDraw_Release(ddraw);
3913 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
3914 DestroyWindow(window);
3917 static void test_primary_palette(void)
3919 DDSCAPS surface_caps = {DDSCAPS_FLIP};
3920 IDirectDrawSurface *primary, *backbuffer;
3921 PALETTEENTRY palette_entries[256];
3922 IDirectDrawPalette *palette, *tmp;
3923 DDSURFACEDESC surface_desc;
3924 IDirectDraw *ddraw;
3925 DWORD palette_caps;
3926 ULONG refcount;
3927 HWND window;
3928 HRESULT hr;
3930 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3931 0, 0, 640, 480, 0, 0, 0, 0);
3932 ddraw = create_ddraw();
3933 ok(!!ddraw, "Failed to create a ddraw object.\n");
3934 if (FAILED(hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 8)))
3936 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
3937 IDirectDraw_Release(ddraw);
3938 DestroyWindow(window);
3939 return;
3941 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3942 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3943 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3945 memset(&surface_desc, 0, sizeof(surface_desc));
3946 surface_desc.dwSize = sizeof(surface_desc);
3947 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
3948 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
3949 surface_desc.dwBackBufferCount = 1;
3950 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
3951 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3952 hr = IDirectDrawSurface_GetAttachedSurface(primary, &surface_caps, &backbuffer);
3953 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3955 memset(palette_entries, 0, sizeof(palette_entries));
3956 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
3957 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
3958 refcount = get_refcount((IUnknown *)palette);
3959 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
3961 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
3962 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
3963 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
3965 hr = IDirectDrawSurface_SetPalette(primary, palette);
3966 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
3967 refcount = get_refcount((IUnknown *)palette);
3968 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
3970 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
3971 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
3972 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
3973 "Got unexpected palette caps %#x.\n", palette_caps);
3975 hr = IDirectDrawSurface_SetPalette(primary, NULL);
3976 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
3977 refcount = get_refcount((IUnknown *)palette);
3978 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
3980 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
3981 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
3982 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
3984 hr = IDirectDrawSurface_SetPalette(primary, palette);
3985 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
3986 refcount = get_refcount((IUnknown *)palette);
3987 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
3989 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
3990 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
3991 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
3992 IDirectDrawPalette_Release(tmp);
3993 hr = IDirectDrawSurface_GetPalette(backbuffer, &tmp);
3994 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
3996 refcount = IDirectDrawPalette_Release(palette);
3997 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
3998 refcount = IDirectDrawPalette_Release(palette);
3999 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4001 /* Note that this only seems to work when the palette is attached to the
4002 * primary surface. When attached to a regular surface, attempting to get
4003 * the palette here will cause an access violation. */
4004 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
4005 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
4007 refcount = IDirectDrawSurface_Release(backbuffer);
4008 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4009 refcount = IDirectDrawSurface_Release(primary);
4010 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4011 refcount = IDirectDraw_Release(ddraw);
4012 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4013 DestroyWindow(window);
4016 static HRESULT WINAPI surface_counter(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
4018 UINT *surface_count = context;
4020 ++(*surface_count);
4021 IDirectDrawSurface_Release(surface);
4023 return DDENUMRET_OK;
4026 static void test_surface_attachment(void)
4028 IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
4029 DDSCAPS caps = {DDSCAPS_TEXTURE};
4030 DDSURFACEDESC surface_desc;
4031 IDirectDraw *ddraw;
4032 UINT surface_count;
4033 ULONG refcount;
4034 HWND window;
4035 HRESULT hr;
4037 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4038 0, 0, 640, 480, 0, 0, 0, 0);
4039 ddraw = create_ddraw();
4040 ok(!!ddraw, "Failed to create a ddraw object.\n");
4041 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4042 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4044 memset(&surface_desc, 0, sizeof(surface_desc));
4045 surface_desc.dwSize = sizeof(surface_desc);
4046 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
4047 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
4048 U2(surface_desc).dwMipMapCount = 3;
4049 surface_desc.dwWidth = 128;
4050 surface_desc.dwHeight = 128;
4051 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4052 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4054 hr = IDirectDrawSurface_GetAttachedSurface(surface1, &caps, &surface2);
4055 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
4056 hr = IDirectDrawSurface_GetAttachedSurface(surface2, &caps, &surface3);
4057 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
4058 hr = IDirectDrawSurface_GetAttachedSurface(surface3, &caps, &surface4);
4059 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
4061 surface_count = 0;
4062 IDirectDrawSurface_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
4063 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
4064 surface_count = 0;
4065 IDirectDrawSurface_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
4066 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
4067 surface_count = 0;
4068 IDirectDrawSurface_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
4069 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
4071 memset(&surface_desc, 0, sizeof(surface_desc));
4072 surface_desc.dwSize = sizeof(surface_desc);
4073 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4074 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
4075 surface_desc.dwWidth = 16;
4076 surface_desc.dwHeight = 16;
4077 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4078 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4080 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
4081 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4082 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4083 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4084 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
4085 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4086 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
4087 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4088 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
4089 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4090 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
4091 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4093 IDirectDrawSurface_Release(surface4);
4095 memset(&surface_desc, 0, sizeof(surface_desc));
4096 surface_desc.dwSize = sizeof(surface_desc);
4097 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4098 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
4099 surface_desc.dwWidth = 16;
4100 surface_desc.dwHeight = 16;
4101 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4102 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4104 if (SUCCEEDED(hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4)))
4106 skip("Running on refrast, skipping some tests.\n");
4107 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface4);
4108 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4110 else
4112 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4113 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4114 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4115 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
4116 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4117 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
4118 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4119 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
4120 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4121 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
4122 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4125 IDirectDrawSurface_Release(surface4);
4126 IDirectDrawSurface_Release(surface3);
4127 IDirectDrawSurface_Release(surface2);
4128 IDirectDrawSurface_Release(surface1);
4130 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4131 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4133 /* Try a single primary and two offscreen plain surfaces. */
4134 memset(&surface_desc, 0, sizeof(surface_desc));
4135 surface_desc.dwSize = sizeof(surface_desc);
4136 surface_desc.dwFlags = DDSD_CAPS;
4137 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4138 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4139 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4141 memset(&surface_desc, 0, sizeof(surface_desc));
4142 surface_desc.dwSize = sizeof(surface_desc);
4143 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4144 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4145 surface_desc.dwWidth = GetSystemMetrics(SM_CXSCREEN);
4146 surface_desc.dwHeight = GetSystemMetrics(SM_CYSCREEN);
4147 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
4148 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4150 memset(&surface_desc, 0, sizeof(surface_desc));
4151 surface_desc.dwSize = sizeof(surface_desc);
4152 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4153 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4154 surface_desc.dwWidth = GetSystemMetrics(SM_CXSCREEN);
4155 surface_desc.dwHeight = GetSystemMetrics(SM_CYSCREEN);
4156 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
4157 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4159 /* This one has a different size. */
4160 memset(&surface_desc, 0, sizeof(surface_desc));
4161 surface_desc.dwSize = sizeof(surface_desc);
4162 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4163 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4164 surface_desc.dwWidth = 128;
4165 surface_desc.dwHeight = 128;
4166 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4167 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4169 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4170 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4171 /* Try the reverse without detaching first. */
4172 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
4173 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
4174 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4175 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4177 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
4178 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4179 /* Try to detach reversed. */
4180 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4181 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
4182 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
4183 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4185 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
4186 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4187 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
4188 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4190 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
4191 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4192 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4193 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4195 IDirectDrawSurface_Release(surface4);
4196 IDirectDrawSurface_Release(surface3);
4197 IDirectDrawSurface_Release(surface2);
4198 IDirectDrawSurface_Release(surface1);
4200 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
4201 memset(&surface_desc, 0, sizeof(surface_desc));
4202 surface_desc.dwSize = sizeof(surface_desc);
4203 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4204 surface_desc.dwWidth = 64;
4205 surface_desc.dwHeight = 64;
4206 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4207 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
4208 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
4209 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
4210 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
4211 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
4212 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
4213 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4214 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4215 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
4216 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4218 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4219 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
4220 U1(surface_desc.ddpfPixelFormat).dwZBufferBitDepth = 16;
4221 U3(surface_desc.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
4222 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
4223 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4225 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4226 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4227 refcount = get_refcount((IUnknown *)surface2);
4228 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4229 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4230 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
4232 /* Attaching while already attached to other surface. */
4233 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
4234 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4235 hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
4236 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4237 IDirectDrawSurface_Release(surface3);
4239 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4240 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4241 refcount = get_refcount((IUnknown *)surface2);
4242 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4244 /* Automatic detachment on release. */
4245 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4246 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4247 refcount = get_refcount((IUnknown *)surface2);
4248 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4249 refcount = IDirectDrawSurface_Release(surface1);
4250 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4251 refcount = IDirectDrawSurface_Release(surface2);
4252 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4253 refcount = IDirectDraw_Release(ddraw);
4254 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4255 DestroyWindow(window);
4258 static void test_pixel_format(void)
4260 HWND window, window2 = NULL;
4261 HDC hdc, hdc2 = NULL;
4262 HMODULE gl = NULL;
4263 int format, test_format;
4264 PIXELFORMATDESCRIPTOR pfd;
4265 IDirectDraw *ddraw = NULL;
4266 IDirectDrawClipper *clipper = NULL;
4267 DDSURFACEDESC ddsd;
4268 IDirectDrawSurface *primary = NULL;
4269 DDBLTFX fx;
4270 HRESULT hr;
4272 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4273 100, 100, 160, 160, NULL, NULL, NULL, NULL);
4274 if (!window)
4276 skip("Failed to create window\n");
4277 return;
4280 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4281 100, 100, 160, 160, NULL, NULL, NULL, NULL);
4283 hdc = GetDC(window);
4284 if (!hdc)
4286 skip("Failed to get DC\n");
4287 goto cleanup;
4290 if (window2)
4291 hdc2 = GetDC(window2);
4293 gl = LoadLibraryA("opengl32.dll");
4294 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
4296 format = GetPixelFormat(hdc);
4297 ok(format == 0, "new window has pixel format %d\n", format);
4299 ZeroMemory(&pfd, sizeof(pfd));
4300 pfd.nSize = sizeof(pfd);
4301 pfd.nVersion = 1;
4302 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
4303 pfd.iPixelType = PFD_TYPE_RGBA;
4304 pfd.iLayerType = PFD_MAIN_PLANE;
4305 format = ChoosePixelFormat(hdc, &pfd);
4306 if (format <= 0)
4308 skip("no pixel format available\n");
4309 goto cleanup;
4312 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
4314 skip("failed to set pixel format\n");
4315 goto cleanup;
4318 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
4320 skip("failed to set pixel format on second window\n");
4321 if (hdc2)
4323 ReleaseDC(window2, hdc2);
4324 hdc2 = NULL;
4328 ddraw = create_ddraw();
4329 ok(!!ddraw, "Failed to create a ddraw object.\n");
4331 test_format = GetPixelFormat(hdc);
4332 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4334 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4335 if (FAILED(hr))
4337 skip("Failed to set cooperative level, hr %#x.\n", hr);
4338 goto cleanup;
4341 test_format = GetPixelFormat(hdc);
4342 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4344 if (hdc2)
4346 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
4347 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
4348 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
4349 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
4351 test_format = GetPixelFormat(hdc);
4352 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4354 test_format = GetPixelFormat(hdc2);
4355 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4358 memset(&ddsd, 0, sizeof(ddsd));
4359 ddsd.dwSize = sizeof(ddsd);
4360 ddsd.dwFlags = DDSD_CAPS;
4361 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4363 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
4364 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4366 test_format = GetPixelFormat(hdc);
4367 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4369 if (hdc2)
4371 test_format = GetPixelFormat(hdc2);
4372 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4375 if (clipper)
4377 hr = IDirectDrawSurface_SetClipper(primary, clipper);
4378 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
4380 test_format = GetPixelFormat(hdc);
4381 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4383 test_format = GetPixelFormat(hdc2);
4384 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4387 memset(&fx, 0, sizeof(fx));
4388 fx.dwSize = sizeof(fx);
4389 hr = IDirectDrawSurface_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4390 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
4392 test_format = GetPixelFormat(hdc);
4393 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4395 if (hdc2)
4397 test_format = GetPixelFormat(hdc2);
4398 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4401 cleanup:
4402 if (primary) IDirectDrawSurface_Release(primary);
4403 if (clipper) IDirectDrawClipper_Release(clipper);
4404 if (ddraw) IDirectDraw_Release(ddraw);
4405 if (gl) FreeLibrary(gl);
4406 if (hdc) ReleaseDC(window, hdc);
4407 if (hdc2) ReleaseDC(window2, hdc2);
4408 if (window) DestroyWindow(window);
4409 if (window2) DestroyWindow(window2);
4412 static void test_create_surface_pitch(void)
4414 IDirectDrawSurface *surface;
4415 DDSURFACEDESC surface_desc;
4416 IDirectDraw *ddraw;
4417 unsigned int i;
4418 ULONG refcount;
4419 HWND window;
4420 HRESULT hr;
4421 void *mem;
4423 static const struct
4425 DWORD placement;
4426 DWORD flags_in;
4427 DWORD pitch_in;
4428 HRESULT hr;
4429 DWORD flags_out;
4430 DWORD pitch_out;
4432 test_data[] =
4434 {DDSCAPS_VIDEOMEMORY, 0, 0, DD_OK,
4435 DDSD_PITCH, 0x100},
4436 {DDSCAPS_VIDEOMEMORY, DDSD_PITCH, 0x104, DD_OK,
4437 DDSD_PITCH, 0x100},
4438 {DDSCAPS_VIDEOMEMORY, DDSD_PITCH, 0x0fc, DD_OK,
4439 DDSD_PITCH, 0x100},
4440 {DDSCAPS_VIDEOMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
4441 0, 0 },
4442 {DDSCAPS_SYSTEMMEMORY, 0, 0, DD_OK,
4443 DDSD_PITCH, 0x100},
4444 {DDSCAPS_SYSTEMMEMORY, DDSD_PITCH, 0x104, DD_OK,
4445 DDSD_PITCH, 0x100},
4446 {DDSCAPS_SYSTEMMEMORY, DDSD_PITCH, 0x0fc, DD_OK,
4447 DDSD_PITCH, 0x100},
4448 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
4449 0, 0 },
4450 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
4451 0, 0 },
4453 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE;
4455 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4456 0, 0, 640, 480, 0, 0, 0, 0);
4457 ddraw = create_ddraw();
4458 ok(!!ddraw, "Failed to create a ddraw object.\n");
4459 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4460 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4462 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((64 * 4) + 4) * 64);
4464 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
4466 memset(&surface_desc, 0, sizeof(surface_desc));
4467 surface_desc.dwSize = sizeof(surface_desc);
4468 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
4469 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | test_data[i].placement;
4470 surface_desc.dwWidth = 64;
4471 surface_desc.dwHeight = 64;
4472 U1(surface_desc).lPitch = test_data[i].pitch_in;
4473 surface_desc.lpSurface = mem;
4474 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
4475 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
4476 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
4477 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4478 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4479 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4480 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4481 ok(hr == test_data[i].hr || (test_data[i].placement == DDSCAPS_VIDEOMEMORY && hr == DDERR_NODIRECTDRAWHW),
4482 "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
4483 if (FAILED(hr))
4484 continue;
4486 memset(&surface_desc, 0, sizeof(surface_desc));
4487 surface_desc.dwSize = sizeof(surface_desc);
4488 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4489 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
4490 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
4491 "Test %u: Got unexpected flags %#x, expected %#x.\n",
4492 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
4493 ok(U1(surface_desc).lPitch == test_data[i].pitch_out,
4494 "Test %u: Got unexpected pitch %u, expected %u.\n",
4495 i, U1(surface_desc).lPitch, test_data[i].pitch_out);
4497 IDirectDrawSurface_Release(surface);
4500 HeapFree(GetProcessHeap(), 0, mem);
4501 refcount = IDirectDraw_Release(ddraw);
4502 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4503 DestroyWindow(window);
4506 START_TEST(ddraw1)
4508 IDirectDraw *ddraw;
4510 if (!(ddraw = create_ddraw()))
4512 skip("Failed to create a ddraw object, skipping tests.\n");
4513 return;
4515 IDirectDraw_Release(ddraw);
4517 test_coop_level_create_device_window();
4518 test_clipper_blt();
4519 test_coop_level_d3d_state();
4520 test_surface_interface_mismatch();
4521 test_coop_level_threaded();
4522 test_viewport();
4523 test_zenable();
4524 test_ck_rgba();
4525 test_ck_default();
4526 test_ck_complex();
4527 test_surface_qi();
4528 test_device_qi();
4529 test_wndproc();
4530 test_window_style();
4531 test_redundant_mode_set();
4532 test_coop_level_mode_set();
4533 test_coop_level_mode_set_multi();
4534 test_initialize();
4535 test_coop_level_surf_create();
4536 test_coop_level_multi_window();
4537 test_clear_rect_count();
4538 test_coop_level_activateapp();
4539 test_unsupported_formats();
4540 test_rt_caps();
4541 test_primary_caps();
4542 test_surface_lock();
4543 test_surface_discard();
4544 test_flip();
4545 test_sysmem_overlay();
4546 test_primary_palette();
4547 test_surface_attachment();
4548 test_pixel_format();
4549 test_create_surface_pitch();