ddraw/tests: Test mipmap GetDC behavior.
[wine.git] / dlls / ddraw / tests / ddraw1.c
blobc993e6fc905fdb41522e47dd339eaf16a98b721a
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, DWORD flags, 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 = flags;
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_ls(void **ptr, D3DLIGHTSTATETYPE state, DWORD value)
149 D3DINSTRUCTION *inst = *ptr;
150 D3DSTATE *ls = (D3DSTATE *)(inst + 1);
152 inst->bOpcode = D3DOP_STATELIGHT;
153 inst->bSize = sizeof(*ls);
154 inst->wCount = 1;
156 U1(*ls).dlstLightStateType = state;
157 U2(*ls).dwArg[0] = value;
159 *ptr = ls + 1;
162 static void emit_set_rs(void **ptr, D3DRENDERSTATETYPE state, DWORD value)
164 D3DINSTRUCTION *inst = *ptr;
165 D3DSTATE *rs = (D3DSTATE *)(inst + 1);
167 inst->bOpcode = D3DOP_STATERENDER;
168 inst->bSize = sizeof(*rs);
169 inst->wCount = 1;
171 U1(*rs).drstRenderStateType = state;
172 U2(*rs).dwArg[0] = value;
174 *ptr = rs + 1;
177 static void emit_tquad(void **ptr, WORD base_idx)
179 D3DINSTRUCTION *inst = *ptr;
180 D3DTRIANGLE *tri = (D3DTRIANGLE *)(inst + 1);
182 inst->bOpcode = D3DOP_TRIANGLE;
183 inst->bSize = sizeof(*tri);
184 inst->wCount = 2;
186 U1(*tri).v1 = base_idx;
187 U2(*tri).v2 = base_idx + 1;
188 U3(*tri).v3 = base_idx + 2;
189 tri->wFlags = D3DTRIFLAG_START;
190 ++tri;
192 U1(*tri).v1 = base_idx + 2;
193 U2(*tri).v2 = base_idx + 1;
194 U3(*tri).v3 = base_idx + 3;
195 tri->wFlags = D3DTRIFLAG_ODD;
196 ++tri;
198 *ptr = tri;
201 static void emit_end(void **ptr)
203 D3DINSTRUCTION *inst = *ptr;
205 inst->bOpcode = D3DOP_EXIT;
206 inst->bSize = 0;
207 inst->wCount = 0;
209 *ptr = inst + 1;
212 static void set_execute_data(IDirect3DExecuteBuffer *execute_buffer, UINT vertex_count, UINT offset, UINT len)
214 D3DEXECUTEDATA exec_data;
215 HRESULT hr;
217 memset(&exec_data, 0, sizeof(exec_data));
218 exec_data.dwSize = sizeof(exec_data);
219 exec_data.dwVertexCount = vertex_count;
220 exec_data.dwInstructionOffset = offset;
221 exec_data.dwInstructionLength = len;
222 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
223 ok(SUCCEEDED(hr), "Failed to set execute data, hr %#x.\n", hr);
226 static DWORD get_device_z_depth(IDirect3DDevice *device)
228 DDSCAPS caps = {DDSCAPS_ZBUFFER};
229 IDirectDrawSurface *ds, *rt;
230 DDSURFACEDESC desc;
231 HRESULT hr;
233 if (FAILED(IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt)))
234 return 0;
236 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ds);
237 IDirectDrawSurface_Release(rt);
238 if (FAILED(hr))
239 return 0;
241 desc.dwSize = sizeof(desc);
242 hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
243 IDirectDrawSurface_Release(ds);
244 if (FAILED(hr))
245 return 0;
247 return U2(desc).dwZBufferBitDepth;
250 static IDirectDraw *create_ddraw(void)
252 IDirectDraw *ddraw;
254 if (FAILED(DirectDrawCreate(NULL, &ddraw, NULL)))
255 return NULL;
257 return ddraw;
260 static IDirect3DDevice *create_device(IDirectDraw *ddraw, HWND window, DWORD coop_level)
262 static const DWORD z_depths[] = {32, 24, 16};
263 IDirectDrawSurface *surface, *ds;
264 IDirect3DDevice *device = NULL;
265 DDSURFACEDESC surface_desc;
266 unsigned int i;
267 HRESULT hr;
269 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, coop_level);
270 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
272 memset(&surface_desc, 0, sizeof(surface_desc));
273 surface_desc.dwSize = sizeof(surface_desc);
274 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
275 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
276 surface_desc.dwWidth = 640;
277 surface_desc.dwHeight = 480;
279 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
280 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
282 if (coop_level & DDSCL_NORMAL)
284 IDirectDrawClipper *clipper;
286 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
287 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
288 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
289 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
290 hr = IDirectDrawSurface_SetClipper(surface, clipper);
291 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
292 IDirectDrawClipper_Release(clipper);
295 /* We used to use EnumDevices() for this, but it seems
296 * D3DDEVICEDESC.dwDeviceZBufferBitDepth only has a very casual
297 * relationship with reality. */
298 for (i = 0; i < sizeof(z_depths) / sizeof(*z_depths); ++i)
300 memset(&surface_desc, 0, sizeof(surface_desc));
301 surface_desc.dwSize = sizeof(surface_desc);
302 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
303 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
304 U2(surface_desc).dwZBufferBitDepth = z_depths[i];
305 surface_desc.dwWidth = 640;
306 surface_desc.dwHeight = 480;
307 if (FAILED(hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL)))
308 continue;
310 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
311 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
312 IDirectDrawSurface_Release(ds);
313 if (FAILED(hr))
314 continue;
316 if (SUCCEEDED(hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device)))
317 break;
319 IDirectDrawSurface_DeleteAttachedSurface(surface, 0, ds);
322 IDirectDrawSurface_Release(surface);
323 return device;
326 static IDirect3DViewport *create_viewport(IDirect3DDevice *device, UINT x, UINT y, UINT w, UINT h)
328 IDirect3DViewport *viewport;
329 D3DVIEWPORT vp;
330 IDirect3D *d3d;
331 HRESULT hr;
333 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
334 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
335 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
336 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
337 hr = IDirect3DDevice_AddViewport(device, viewport);
338 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
339 memset(&vp, 0, sizeof(vp));
340 vp.dwSize = sizeof(vp);
341 vp.dwX = x;
342 vp.dwY = y;
343 vp.dwWidth = w;
344 vp.dwHeight = h;
345 vp.dvScaleX = (float)w / 2.0f;
346 vp.dvScaleY = (float)h / 2.0f;
347 vp.dvMaxX = 1.0f;
348 vp.dvMaxY = 1.0f;
349 vp.dvMinZ = 0.0f;
350 vp.dvMaxZ = 1.0f;
351 hr = IDirect3DViewport_SetViewport(viewport, &vp);
352 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
353 IDirect3D_Release(d3d);
355 return viewport;
358 static void viewport_set_background(IDirect3DDevice *device, IDirect3DViewport *viewport,
359 IDirect3DMaterial *material)
361 D3DMATERIALHANDLE material_handle;
362 HRESULT hr;
364 hr = IDirect3DMaterial2_GetHandle(material, device, &material_handle);
365 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
366 hr = IDirect3DViewport2_SetBackground(viewport, material_handle);
367 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
370 static void destroy_viewport(IDirect3DDevice *device, IDirect3DViewport *viewport)
372 HRESULT hr;
374 hr = IDirect3DDevice_DeleteViewport(device, viewport);
375 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
376 IDirect3DViewport_Release(viewport);
379 static IDirect3DMaterial *create_material(IDirect3DDevice *device, D3DMATERIAL *mat)
381 IDirect3DMaterial *material;
382 IDirect3D *d3d;
383 HRESULT hr;
385 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
386 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
387 hr = IDirect3D_CreateMaterial(d3d, &material, NULL);
388 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
389 hr = IDirect3DMaterial_SetMaterial(material, mat);
390 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
391 IDirect3D_Release(d3d);
393 return material;
396 static IDirect3DMaterial *create_diffuse_material(IDirect3DDevice *device, float r, float g, float b, float a)
398 D3DMATERIAL mat;
400 memset(&mat, 0, sizeof(mat));
401 mat.dwSize = sizeof(mat);
402 U1(U(mat).diffuse).r = r;
403 U2(U(mat).diffuse).g = g;
404 U3(U(mat).diffuse).b = b;
405 U4(U(mat).diffuse).a = a;
407 return create_material(device, &mat);
410 static IDirect3DMaterial *create_emissive_material(IDirect3DDevice *device, float r, float g, float b, float a)
412 D3DMATERIAL mat;
414 memset(&mat, 0, sizeof(mat));
415 mat.dwSize = sizeof(mat);
416 U1(U3(mat).emissive).r = r;
417 U2(U3(mat).emissive).g = g;
418 U3(U3(mat).emissive).b = b;
419 U4(U3(mat).emissive).a = a;
421 return create_material(device, &mat);
424 static void destroy_material(IDirect3DMaterial *material)
426 IDirect3DMaterial_Release(material);
429 static const UINT *expect_messages;
431 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
433 if (expect_messages && message == *expect_messages)
434 ++expect_messages;
436 return DefWindowProcA(hwnd, message, wparam, lparam);
439 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
440 * interface. This prevents subsequent SetCooperativeLevel() calls on a
441 * different window from failing with DDERR_HWNDALREADYSET. */
442 static void fix_wndproc(HWND window, LONG_PTR proc)
444 IDirectDraw *ddraw;
445 HRESULT hr;
447 if (!(ddraw = create_ddraw()))
448 return;
450 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
451 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
452 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
453 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
454 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
456 IDirectDraw_Release(ddraw);
459 static HRESULT CALLBACK restore_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
461 HRESULT hr = IDirectDrawSurface_Restore(surface);
462 ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
463 IDirectDrawSurface_Release(surface);
465 return DDENUMRET_OK;
468 static HRESULT restore_surfaces(IDirectDraw *ddraw)
470 return IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
471 NULL, NULL, restore_callback);
474 static void test_coop_level_create_device_window(void)
476 HWND focus_window, device_window;
477 IDirectDraw *ddraw;
478 HRESULT hr;
480 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
481 0, 0, 640, 480, 0, 0, 0, 0);
482 ddraw = create_ddraw();
483 ok(!!ddraw, "Failed to create a ddraw object.\n");
485 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
486 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
487 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
488 ok(!device_window, "Unexpected device window found.\n");
489 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
490 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
491 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
492 ok(!device_window, "Unexpected device window found.\n");
493 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
494 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
495 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
496 ok(!device_window, "Unexpected device window found.\n");
497 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
498 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
499 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
500 ok(!device_window, "Unexpected device window found.\n");
501 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
502 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
503 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
504 ok(!device_window, "Unexpected device window found.\n");
506 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
507 if (broken(hr == DDERR_INVALIDPARAMS))
509 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
510 IDirectDraw_Release(ddraw);
511 DestroyWindow(focus_window);
512 return;
515 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
516 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
517 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
518 ok(!device_window, "Unexpected device window found.\n");
519 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
520 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
521 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
522 ok(!device_window, "Unexpected device window found.\n");
524 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
525 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
526 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
527 ok(!device_window, "Unexpected device window found.\n");
528 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
529 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
530 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
531 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
532 ok(!!device_window, "Device window not found.\n");
534 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
535 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
536 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
537 ok(!device_window, "Unexpected device window found.\n");
538 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
539 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
540 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
541 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
542 ok(!!device_window, "Device window not found.\n");
544 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
545 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
546 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
547 ok(!device_window, "Unexpected device window found.\n");
548 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
549 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
550 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
551 ok(!device_window, "Unexpected device window found.\n");
552 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
553 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
554 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
555 ok(!device_window, "Unexpected device window found.\n");
556 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
557 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
558 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
559 ok(!!device_window, "Device window not found.\n");
561 IDirectDraw_Release(ddraw);
562 DestroyWindow(focus_window);
565 static void test_clipper_blt(void)
567 IDirectDrawSurface *src_surface, *dst_surface;
568 RECT client_rect, src_rect;
569 IDirectDrawClipper *clipper;
570 DDSURFACEDESC surface_desc;
571 unsigned int i, j, x, y;
572 IDirectDraw *ddraw;
573 RGNDATA *rgn_data;
574 D3DCOLOR color;
575 HRGN r1, r2;
576 HWND window;
577 DDBLTFX fx;
578 HRESULT hr;
579 DWORD *ptr;
580 DWORD ret;
582 static const DWORD src_data[] =
584 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
585 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
586 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
588 static const D3DCOLOR expected1[] =
590 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
591 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
592 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
593 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
595 /* Nvidia on Windows seems to have an off-by-one error
596 * when processing source rectangles. Our left = 1 and
597 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
598 * read as well, but only for the edge pixels on the
599 * output image. The bug happens on the y axis as well,
600 * but we only read one row there, and all source rows
601 * contain the same data. This bug is not dependent on
602 * the presence of a clipper. */
603 static const D3DCOLOR expected1_broken[] =
605 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
606 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
607 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
608 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
610 static const D3DCOLOR expected2[] =
612 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
613 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
614 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
615 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
618 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
619 10, 10, 640, 480, 0, 0, 0, 0);
620 ShowWindow(window, SW_SHOW);
621 ddraw = create_ddraw();
622 ok(!!ddraw, "Failed to create a ddraw object.\n");
624 ret = GetClientRect(window, &client_rect);
625 ok(ret, "Failed to get client rect.\n");
626 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
627 ok(ret, "Failed to map client rect.\n");
629 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
630 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
632 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
633 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
634 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
635 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
636 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
637 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
638 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
639 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
640 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
641 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
642 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
643 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
644 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
645 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
646 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
647 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
648 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
649 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
650 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
651 HeapFree(GetProcessHeap(), 0, rgn_data);
653 r1 = CreateRectRgn(0, 0, 320, 240);
654 ok(!!r1, "Failed to create region.\n");
655 r2 = CreateRectRgn(320, 240, 640, 480);
656 ok(!!r2, "Failed to create region.\n");
657 CombineRgn(r1, r1, r2, RGN_OR);
658 ret = GetRegionData(r1, 0, NULL);
659 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
660 ret = GetRegionData(r1, ret, rgn_data);
661 ok(!!ret, "Failed to get region data.\n");
663 DeleteObject(r2);
664 DeleteObject(r1);
666 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
667 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
668 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
669 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
670 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
671 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
673 HeapFree(GetProcessHeap(), 0, rgn_data);
675 memset(&surface_desc, 0, sizeof(surface_desc));
676 surface_desc.dwSize = sizeof(surface_desc);
677 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
678 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
679 surface_desc.dwWidth = 640;
680 surface_desc.dwHeight = 480;
681 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
682 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
683 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
684 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
685 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
686 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
688 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
689 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
690 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
691 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
693 memset(&fx, 0, sizeof(fx));
694 fx.dwSize = sizeof(fx);
695 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
696 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
697 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
698 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
700 hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
701 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
702 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
703 ptr = surface_desc.lpSurface;
704 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
705 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
706 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
707 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
708 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
710 hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
711 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
713 SetRect(&src_rect, 1, 1, 5, 2);
714 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
715 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
716 for (i = 0; i < 4; ++i)
718 for (j = 0; j < 4; ++j)
720 x = 80 * ((2 * j) + 1);
721 y = 60 * ((2 * i) + 1);
722 color = get_surface_color(dst_surface, x, y);
723 ok(compare_color(color, expected1[i * 4 + j], 1)
724 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
725 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
729 U5(fx).dwFillColor = 0xff0000ff;
730 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
731 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
732 for (i = 0; i < 4; ++i)
734 for (j = 0; j < 4; ++j)
736 x = 80 * ((2 * j) + 1);
737 y = 60 * ((2 * i) + 1);
738 color = get_surface_color(dst_surface, x, y);
739 ok(compare_color(color, expected2[i * 4 + j], 1),
740 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
744 hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
745 ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
747 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
748 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
749 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
750 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
751 DestroyWindow(window);
752 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
753 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
754 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
755 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
756 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
757 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
758 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
759 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
760 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
761 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
762 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
763 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
765 IDirectDrawSurface_Release(dst_surface);
766 IDirectDrawSurface_Release(src_surface);
767 IDirectDrawClipper_Release(clipper);
768 IDirectDraw_Release(ddraw);
771 static void test_coop_level_d3d_state(void)
773 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
774 IDirectDrawSurface *rt, *surface;
775 IDirect3DMaterial *background;
776 IDirect3DViewport *viewport;
777 IDirect3DDevice *device;
778 D3DMATERIAL material;
779 IDirectDraw *ddraw;
780 D3DCOLOR color;
781 HWND window;
782 HRESULT hr;
784 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
785 0, 0, 640, 480, 0, 0, 0, 0);
786 ddraw = create_ddraw();
787 ok(!!ddraw, "Failed to create a ddraw object.\n");
788 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
790 skip("Failed to create a 3D device, skipping test.\n");
791 IDirectDraw_Release(ddraw);
792 DestroyWindow(window);
793 return;
796 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
797 viewport = create_viewport(device, 0, 0, 640, 480);
798 viewport_set_background(device, viewport, background);
800 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
801 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
802 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
803 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
804 color = get_surface_color(rt, 320, 240);
805 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
807 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
808 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
809 hr = IDirectDrawSurface_IsLost(rt);
810 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
811 hr = restore_surfaces(ddraw);
812 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
814 memset(&material, 0, sizeof(material));
815 material.dwSize = sizeof(material);
816 U1(U(material).diffuse).r = 0.0f;
817 U2(U(material).diffuse).g = 1.0f;
818 U3(U(material).diffuse).b = 0.0f;
819 U4(U(material).diffuse).a = 1.0f;
820 hr = IDirect3DMaterial_SetMaterial(background, &material);
821 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
823 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&surface);
824 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
825 ok(surface == rt, "Got unexpected surface %p.\n", surface);
826 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
827 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
828 color = get_surface_color(rt, 320, 240);
829 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
831 destroy_viewport(device, viewport);
832 destroy_material(background);
833 IDirectDrawSurface_Release(surface);
834 IDirectDrawSurface_Release(rt);
835 IDirect3DDevice_Release(device);
836 IDirectDraw_Release(ddraw);
837 DestroyWindow(window);
840 static void test_surface_interface_mismatch(void)
842 IDirectDraw *ddraw = NULL;
843 IDirectDrawSurface *surface = NULL, *ds;
844 IDirectDrawSurface3 *surface3 = NULL;
845 IDirect3DDevice *device = NULL;
846 IDirect3DViewport *viewport = NULL;
847 IDirect3DMaterial *background = NULL;
848 DDSURFACEDESC surface_desc;
849 DWORD z_depth = 0;
850 ULONG refcount;
851 HRESULT hr;
852 D3DCOLOR color;
853 HWND window;
854 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
856 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
857 0, 0, 640, 480, 0, 0, 0, 0);
858 ddraw = create_ddraw();
859 ok(!!ddraw, "Failed to create a ddraw object.\n");
860 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
862 skip("Failed to create a 3D device, skipping test.\n");
863 IDirectDraw_Release(ddraw);
864 DestroyWindow(window);
865 return;
867 z_depth = get_device_z_depth(device);
868 ok(!!z_depth, "Failed to get device z depth.\n");
869 IDirect3DDevice_Release(device);
870 device = NULL;
872 memset(&surface_desc, 0, sizeof(surface_desc));
873 surface_desc.dwSize = sizeof(surface_desc);
874 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
875 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
876 surface_desc.dwWidth = 640;
877 surface_desc.dwHeight = 480;
879 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
880 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
882 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
883 if (FAILED(hr))
885 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
886 goto cleanup;
889 memset(&surface_desc, 0, sizeof(surface_desc));
890 surface_desc.dwSize = sizeof(surface_desc);
891 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
892 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
893 U2(surface_desc).dwZBufferBitDepth = z_depth;
894 surface_desc.dwWidth = 640;
895 surface_desc.dwHeight = 480;
896 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL);
897 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
898 if (FAILED(hr))
899 goto cleanup;
901 /* Using a different surface interface version still works */
902 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
903 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
904 refcount = IDirectDrawSurface_Release(ds);
905 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
906 if (FAILED(hr))
907 goto cleanup;
909 /* Here too */
910 hr = IDirectDrawSurface3_QueryInterface(surface3, &IID_IDirect3DHALDevice, (void **)&device);
911 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
912 if (FAILED(hr))
913 goto cleanup;
915 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
916 viewport = create_viewport(device, 0, 0, 640, 480);
917 viewport_set_background(device, viewport, background);
919 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
920 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
921 color = get_surface_color(surface, 320, 240);
922 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
924 cleanup:
925 if (viewport)
926 destroy_viewport(device, viewport);
927 if (background)
928 destroy_material(background);
929 if (surface3) IDirectDrawSurface3_Release(surface3);
930 if (surface) IDirectDrawSurface_Release(surface);
931 if (device) IDirect3DDevice_Release(device);
932 if (ddraw) IDirectDraw_Release(ddraw);
933 DestroyWindow(window);
936 static void test_coop_level_threaded(void)
938 struct create_window_thread_param p;
939 IDirectDraw *ddraw;
940 HRESULT hr;
942 ddraw = create_ddraw();
943 ok(!!ddraw, "Failed to create a ddraw object.\n");
944 create_window_thread(&p);
946 hr = IDirectDraw_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
947 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
949 IDirectDraw_Release(ddraw);
950 destroy_window_thread(&p);
953 static ULONG get_refcount(IUnknown *test_iface)
955 IUnknown_AddRef(test_iface);
956 return IUnknown_Release(test_iface);
959 static void test_viewport(void)
961 IDirectDraw *ddraw;
962 IDirect3D *d3d;
963 HRESULT hr;
964 ULONG ref;
965 IDirect3DViewport *viewport, *another_vp;
966 IDirect3DViewport2 *viewport2;
967 IDirect3DViewport3 *viewport3;
968 IDirectDrawGammaControl *gamma;
969 IUnknown *unknown;
970 IDirect3DDevice *device;
971 HWND window;
973 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
974 0, 0, 640, 480, 0, 0, 0, 0);
975 ddraw = create_ddraw();
976 ok(!!ddraw, "Failed to create a ddraw object.\n");
977 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
979 skip("Failed to create a 3D device, skipping test.\n");
980 IDirectDraw_Release(ddraw);
981 DestroyWindow(window);
982 return;
985 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
986 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
987 ref = get_refcount((IUnknown *) d3d);
988 ok(ref == 2, "IDirect3D refcount is %d\n", ref);
990 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
991 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
992 ref = get_refcount((IUnknown *)viewport);
993 ok(ref == 1, "Initial IDirect3DViewport refcount is %u\n", ref);
994 ref = get_refcount((IUnknown *)d3d);
995 ok(ref == 2, "IDirect3D refcount is %u\n", ref);
997 /* E_FAIL return values are returned by Winetestbot Windows NT machines. While not supporting
998 * newer interfaces is legitimate for old ddraw versions, E_FAIL violates Microsoft's rules
999 * for QueryInterface, hence the broken() */
1000 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1001 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirectDrawGammaControl, (void **)&gamma);
1002 ok(hr == E_NOINTERFACE || broken(hr == E_FAIL), "Got unexpected hr %#x.\n", hr);
1003 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1004 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1005 /* NULL iid: Segfaults */
1007 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport2, (void **)&viewport2);
1008 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
1009 "Failed to QI IDirect3DViewport2, hr %#x.\n", hr);
1010 if (viewport2)
1012 ref = get_refcount((IUnknown *)viewport);
1013 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1014 ref = get_refcount((IUnknown *)viewport2);
1015 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1016 IDirect3DViewport2_Release(viewport2);
1017 viewport2 = NULL;
1020 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport3, (void **)&viewport3);
1021 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
1022 "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1023 if (viewport3)
1025 ref = get_refcount((IUnknown *)viewport);
1026 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1027 ref = get_refcount((IUnknown *)viewport3);
1028 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1029 IDirect3DViewport3_Release(viewport3);
1032 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IUnknown, (void **)&unknown);
1033 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1034 if (unknown)
1036 ref = get_refcount((IUnknown *)viewport);
1037 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1038 ref = get_refcount(unknown);
1039 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1040 IUnknown_Release(unknown);
1043 /* AddViewport(NULL): Segfault */
1044 hr = IDirect3DDevice_DeleteViewport(device, NULL);
1045 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1047 hr = IDirect3D_CreateViewport(d3d, &another_vp, NULL);
1048 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1050 hr = IDirect3DDevice_AddViewport(device, viewport);
1051 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1052 ref = get_refcount((IUnknown *) viewport);
1053 ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
1054 hr = IDirect3DDevice_AddViewport(device, another_vp);
1055 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1056 ref = get_refcount((IUnknown *) another_vp);
1057 ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
1059 hr = IDirect3DDevice_DeleteViewport(device, another_vp);
1060 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1061 ref = get_refcount((IUnknown *) another_vp);
1062 ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
1064 IDirect3DDevice_Release(device);
1065 ref = get_refcount((IUnknown *) viewport);
1066 ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
1068 IDirect3DViewport_Release(another_vp);
1069 IDirect3D_Release(d3d);
1070 IDirect3DViewport_Release(viewport);
1071 DestroyWindow(window);
1072 IDirectDraw_Release(ddraw);
1075 static void test_zenable(void)
1077 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1078 static D3DTLVERTEX tquad[] =
1080 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1081 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1082 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1083 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1085 IDirect3DExecuteBuffer *execute_buffer;
1086 D3DEXECUTEBUFFERDESC exec_desc;
1087 IDirect3DMaterial *background;
1088 IDirect3DViewport *viewport;
1089 IDirect3DDevice *device;
1090 IDirectDrawSurface *rt;
1091 IDirectDraw *ddraw;
1092 UINT inst_length;
1093 D3DCOLOR color;
1094 HWND window;
1095 HRESULT hr;
1096 UINT x, y;
1097 UINT i, j;
1098 void *ptr;
1100 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1101 0, 0, 640, 480, 0, 0, 0, 0);
1102 ddraw = create_ddraw();
1103 ok(!!ddraw, "Failed to create a ddraw object.\n");
1104 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1106 skip("Failed to create a 3D device, skipping test.\n");
1107 IDirectDraw_Release(ddraw);
1108 DestroyWindow(window);
1109 return;
1112 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1113 viewport = create_viewport(device, 0, 0, 640, 480);
1114 viewport_set_background(device, viewport, background);
1116 memset(&exec_desc, 0, sizeof(exec_desc));
1117 exec_desc.dwSize = sizeof(exec_desc);
1118 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1119 exec_desc.dwBufferSize = 1024;
1120 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1122 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1123 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1124 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1125 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1126 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1127 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1128 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1129 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1130 emit_tquad(&ptr, 0);
1131 emit_end(&ptr);
1132 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
1133 inst_length -= sizeof(tquad);
1134 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1135 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1137 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1138 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1139 hr = IDirect3DDevice_BeginScene(device);
1140 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1141 set_execute_data(execute_buffer, 4, sizeof(tquad), inst_length);
1142 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1143 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1144 hr = IDirect3DDevice_EndScene(device);
1145 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1147 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1148 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1149 for (i = 0; i < 4; ++i)
1151 for (j = 0; j < 4; ++j)
1153 x = 80 * ((2 * j) + 1);
1154 y = 60 * ((2 * i) + 1);
1155 color = get_surface_color(rt, x, y);
1156 ok(compare_color(color, 0x0000ff00, 1),
1157 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1160 IDirectDrawSurface_Release(rt);
1162 destroy_viewport(device, viewport);
1163 IDirect3DExecuteBuffer_Release(execute_buffer);
1164 destroy_material(background);
1165 IDirect3DDevice_Release(device);
1166 IDirectDraw_Release(ddraw);
1167 DestroyWindow(window);
1170 static void test_ck_rgba(void)
1172 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1173 static D3DTLVERTEX tquad[] =
1175 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1176 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1177 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1178 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1179 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1180 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1181 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1182 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1184 static const struct
1186 D3DCOLOR fill_color;
1187 BOOL color_key;
1188 BOOL blend;
1189 D3DCOLOR result1;
1190 D3DCOLOR result2;
1192 tests[] =
1194 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x000000ff},
1195 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x000000ff},
1196 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00},
1197 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1198 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00807f00},
1199 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x0000ff00},
1200 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00},
1201 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1204 IDirect3DExecuteBuffer *execute_buffer;
1205 D3DTEXTUREHANDLE texture_handle;
1206 D3DEXECUTEBUFFERDESC exec_desc;
1207 IDirect3DMaterial *background;
1208 IDirectDrawSurface *surface;
1209 IDirect3DViewport *viewport;
1210 DDSURFACEDESC surface_desc;
1211 IDirect3DTexture *texture;
1212 IDirect3DDevice *device;
1213 IDirectDrawSurface *rt;
1214 IDirectDraw *ddraw;
1215 D3DCOLOR color;
1216 HWND window;
1217 DDBLTFX fx;
1218 HRESULT hr;
1219 UINT i;
1221 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1222 0, 0, 640, 480, 0, 0, 0, 0);
1223 ddraw = create_ddraw();
1224 ok(!!ddraw, "Failed to create a ddraw object.\n");
1225 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1227 skip("Failed to create a 3D device, skipping test.\n");
1228 IDirectDraw_Release(ddraw);
1229 DestroyWindow(window);
1230 return;
1233 background = create_diffuse_material(device, 1.0, 0.0f, 0.0f, 1.0f);
1234 viewport = create_viewport(device, 0, 0, 640, 480);
1235 viewport_set_background(device, viewport, background);
1237 memset(&surface_desc, 0, sizeof(surface_desc));
1238 surface_desc.dwSize = sizeof(surface_desc);
1239 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1240 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1241 surface_desc.dwWidth = 256;
1242 surface_desc.dwHeight = 256;
1243 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1244 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1245 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1246 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1247 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1248 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1249 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1250 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1251 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1252 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1253 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1254 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1255 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1256 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1257 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1258 IDirect3DTexture_Release(texture);
1260 memset(&exec_desc, 0, sizeof(exec_desc));
1261 exec_desc.dwSize = sizeof(exec_desc);
1262 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1263 exec_desc.dwBufferSize = 1024;
1264 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1265 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1266 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1268 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1269 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1271 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1273 UINT draw1_len, draw2_len;
1274 void *ptr;
1276 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1277 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1278 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1279 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1280 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1281 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1282 emit_set_rs(&ptr, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1283 emit_set_rs(&ptr, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1284 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1285 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1286 emit_tquad(&ptr, 0);
1287 emit_end(&ptr);
1288 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - sizeof(tquad);
1289 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 4, 4);
1290 emit_tquad(&ptr, 0);
1291 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1292 emit_end(&ptr);
1293 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_len;
1294 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1295 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1297 memset(&fx, 0, sizeof(fx));
1298 fx.dwSize = sizeof(fx);
1299 U5(fx).dwFillColor = tests[i].fill_color;
1300 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1301 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1303 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1304 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1305 hr = IDirect3DDevice_BeginScene(device);
1306 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1307 set_execute_data(execute_buffer, 8, sizeof(tquad), draw1_len);
1308 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1309 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1310 hr = IDirect3DDevice_EndScene(device);
1311 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1313 color = get_surface_color(rt, 320, 240);
1314 if (i == 2)
1315 todo_wine ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1316 tests[i].result1, i, color);
1317 else
1318 ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1319 tests[i].result1, i, color);
1321 U5(fx).dwFillColor = 0xff0000ff;
1322 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1323 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1325 hr = IDirect3DDevice_BeginScene(device);
1326 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1327 set_execute_data(execute_buffer, 8, sizeof(tquad) + draw1_len, draw2_len);
1328 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1329 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1330 hr = IDirect3DDevice_EndScene(device);
1331 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1333 /* This tests that fragments that are masked out by the color key are
1334 * discarded, instead of just fully transparent. */
1335 color = get_surface_color(rt, 320, 240);
1336 if (i == 2)
1337 todo_wine ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1338 tests[i].result2, i, color);
1339 else
1340 ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1341 tests[i].result2, i, color);
1344 IDirectDrawSurface_Release(rt);
1345 IDirect3DExecuteBuffer_Release(execute_buffer);
1346 IDirectDrawSurface_Release(surface);
1347 destroy_viewport(device, viewport);
1348 destroy_material(background);
1349 IDirect3DDevice_Release(device);
1350 IDirectDraw_Release(ddraw);
1351 DestroyWindow(window);
1354 static void test_ck_default(void)
1356 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1357 static D3DTLVERTEX tquad[] =
1359 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1360 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1361 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1362 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1364 IDirect3DExecuteBuffer *execute_buffer;
1365 IDirectDrawSurface *surface, *rt;
1366 D3DTEXTUREHANDLE texture_handle;
1367 D3DEXECUTEBUFFERDESC exec_desc;
1368 IDirect3DMaterial *background;
1369 UINT draw1_offset, draw1_len;
1370 UINT draw2_offset, draw2_len;
1371 UINT draw3_offset, draw3_len;
1372 UINT draw4_offset, draw4_len;
1373 IDirect3DViewport *viewport;
1374 DDSURFACEDESC surface_desc;
1375 IDirect3DTexture *texture;
1376 IDirect3DDevice *device;
1377 IDirectDraw *ddraw;
1378 D3DCOLOR color;
1379 HWND window;
1380 DDBLTFX fx;
1381 HRESULT hr;
1382 void *ptr;
1384 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1385 0, 0, 640, 480, 0, 0, 0, 0);
1386 ddraw = create_ddraw();
1387 ok(!!ddraw, "Failed to create a ddraw object.\n");
1388 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1390 skip("Failed to create a 3D device, skipping test.\n");
1391 IDirectDraw_Release(ddraw);
1392 DestroyWindow(window);
1393 return;
1396 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1397 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1399 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
1400 viewport = create_viewport(device, 0, 0, 640, 480);
1401 viewport_set_background(device, viewport, background);
1403 memset(&surface_desc, 0, sizeof(surface_desc));
1404 surface_desc.dwSize = sizeof(surface_desc);
1405 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1406 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1407 surface_desc.dwWidth = 256;
1408 surface_desc.dwHeight = 256;
1409 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1410 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1411 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1412 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1413 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1414 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1415 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1416 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1417 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1418 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1419 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1420 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1421 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1422 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1423 IDirect3DTexture_Release(texture);
1425 memset(&fx, 0, sizeof(fx));
1426 fx.dwSize = sizeof(fx);
1427 U5(fx).dwFillColor = 0x000000ff;
1428 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1429 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1431 memset(&exec_desc, 0, sizeof(exec_desc));
1432 exec_desc.dwSize = sizeof(exec_desc);
1433 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1434 exec_desc.dwBufferSize = 1024;
1435 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1436 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1437 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1439 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1440 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1441 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1442 ptr = (BYTE *)exec_desc.lpData + sizeof(tquad);
1443 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1444 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1445 emit_tquad(&ptr, 0);
1446 emit_end(&ptr);
1447 draw1_offset = sizeof(tquad);
1448 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_offset;
1449 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1450 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, FALSE);
1451 emit_tquad(&ptr, 0);
1452 emit_end(&ptr);
1453 draw2_offset = draw1_offset + draw1_len;
1454 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw2_offset;
1455 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1456 emit_tquad(&ptr, 0);
1457 emit_end(&ptr);
1458 draw3_offset = draw2_offset + draw2_len;
1459 draw3_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw3_offset;
1460 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1461 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1462 emit_tquad(&ptr, 0);
1463 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1464 emit_end(&ptr);
1465 draw4_offset = draw3_offset + draw3_len;
1466 draw4_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw4_offset;
1467 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1468 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1470 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1471 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1472 hr = IDirect3DDevice_BeginScene(device);
1473 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1474 set_execute_data(execute_buffer, 4, draw1_offset, draw1_len);
1475 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1476 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1477 hr = IDirect3DDevice_EndScene(device);
1478 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1479 color = get_surface_color(rt, 320, 240);
1480 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1482 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1483 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1484 hr = IDirect3DDevice_BeginScene(device);
1485 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1486 set_execute_data(execute_buffer, 4, draw2_offset, draw2_len);
1487 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1488 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1489 hr = IDirect3DDevice_EndScene(device);
1490 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1491 color = get_surface_color(rt, 320, 240);
1492 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1494 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1495 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1496 hr = IDirect3DDevice_BeginScene(device);
1497 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1498 set_execute_data(execute_buffer, 4, draw3_offset, draw3_len);
1499 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1500 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1501 hr = IDirect3DDevice_EndScene(device);
1502 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1503 color = get_surface_color(rt, 320, 240);
1504 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1506 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1507 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1508 hr = IDirect3DDevice_BeginScene(device);
1509 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1510 set_execute_data(execute_buffer, 4, draw4_offset, draw4_len);
1511 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1512 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1513 hr = IDirect3DDevice_EndScene(device);
1514 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1515 color = get_surface_color(rt, 320, 240);
1516 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1518 IDirect3DExecuteBuffer_Release(execute_buffer);
1519 IDirectDrawSurface_Release(surface);
1520 destroy_viewport(device, viewport);
1521 destroy_material(background);
1522 IDirectDrawSurface_Release(rt);
1523 IDirect3DDevice_Release(device);
1524 IDirectDraw_Release(ddraw);
1525 DestroyWindow(window);
1528 static void test_ck_complex(void)
1530 IDirectDrawSurface *surface, *mipmap, *tmp;
1531 DDSCAPS caps = {DDSCAPS_COMPLEX};
1532 DDSURFACEDESC surface_desc;
1533 IDirect3DDevice *device;
1534 DDCOLORKEY color_key;
1535 IDirectDraw *ddraw;
1536 unsigned int i;
1537 ULONG refcount;
1538 HWND window;
1539 HRESULT hr;
1541 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1542 0, 0, 640, 480, 0, 0, 0, 0);
1543 ddraw = create_ddraw();
1544 ok(!!ddraw, "Failed to create a ddraw object.\n");
1545 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1547 skip("Failed to create a 3D device, skipping test.\n");
1548 DestroyWindow(window);
1549 IDirectDraw2_Release(ddraw);
1550 return;
1552 IDirect3DDevice_Release(device);
1554 memset(&surface_desc, 0, sizeof(surface_desc));
1555 surface_desc.dwSize = sizeof(surface_desc);
1556 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1557 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1558 surface_desc.dwWidth = 128;
1559 surface_desc.dwHeight = 128;
1560 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1561 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1563 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1564 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1565 color_key.dwColorSpaceLowValue = 0x0000ff00;
1566 color_key.dwColorSpaceHighValue = 0x0000ff00;
1567 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1568 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1569 memset(&color_key, 0, sizeof(color_key));
1570 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1571 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1572 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1573 color_key.dwColorSpaceLowValue);
1574 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1575 color_key.dwColorSpaceHighValue);
1577 mipmap = surface;
1578 IDirectDrawSurface_AddRef(mipmap);
1579 for (i = 0; i < 7; ++i)
1581 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1582 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1584 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1585 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1586 color_key.dwColorSpaceLowValue = 0x000000ff;
1587 color_key.dwColorSpaceHighValue = 0x000000ff;
1588 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1589 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x, i %u.\n", hr, i);
1590 memset(&color_key, 0, sizeof(color_key));
1591 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1592 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x, i %u.\n", hr, i);
1593 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1594 color_key.dwColorSpaceLowValue, i);
1595 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1596 color_key.dwColorSpaceHighValue, i);
1598 IDirectDrawSurface_Release(mipmap);
1599 mipmap = tmp;
1602 memset(&color_key, 0, sizeof(color_key));
1603 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1604 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1605 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1606 color_key.dwColorSpaceLowValue);
1607 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1608 color_key.dwColorSpaceHighValue);
1610 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1611 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1612 IDirectDrawSurface_Release(mipmap);
1613 refcount = IDirectDrawSurface_Release(surface);
1614 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1616 memset(&surface_desc, 0, sizeof(surface_desc));
1617 surface_desc.dwSize = sizeof(surface_desc);
1618 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1619 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1620 surface_desc.dwBackBufferCount = 1;
1621 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1622 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1624 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1625 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1626 color_key.dwColorSpaceLowValue = 0x0000ff00;
1627 color_key.dwColorSpaceHighValue = 0x0000ff00;
1628 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1629 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1630 memset(&color_key, 0, sizeof(color_key));
1631 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1632 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1633 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1634 color_key.dwColorSpaceLowValue);
1635 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1636 color_key.dwColorSpaceHighValue);
1638 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
1639 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1641 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1642 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1643 color_key.dwColorSpaceLowValue = 0x0000ff00;
1644 color_key.dwColorSpaceHighValue = 0x0000ff00;
1645 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1646 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1647 memset(&color_key, 0, sizeof(color_key));
1648 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1649 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1650 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1651 color_key.dwColorSpaceLowValue);
1652 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1653 color_key.dwColorSpaceHighValue);
1655 IDirectDrawSurface_Release(tmp);
1657 refcount = IDirectDrawSurface_Release(surface);
1658 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1659 refcount = IDirectDraw_Release(ddraw);
1660 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1661 DestroyWindow(window);
1664 struct qi_test
1666 REFIID iid;
1667 REFIID refcount_iid;
1668 HRESULT hr;
1671 static void test_qi(const char *test_name, IUnknown *base_iface,
1672 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1674 ULONG refcount, expected_refcount;
1675 IUnknown *iface1, *iface2;
1676 HRESULT hr;
1677 UINT i, j;
1679 for (i = 0; i < entry_count; ++i)
1681 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1682 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1683 if (SUCCEEDED(hr))
1685 for (j = 0; j < entry_count; ++j)
1687 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1688 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1689 if (SUCCEEDED(hr))
1691 expected_refcount = 0;
1692 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1693 ++expected_refcount;
1694 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1695 ++expected_refcount;
1696 refcount = IUnknown_Release(iface2);
1697 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1698 refcount, test_name, i, j, expected_refcount);
1702 expected_refcount = 0;
1703 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1704 ++expected_refcount;
1705 refcount = IUnknown_Release(iface1);
1706 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1707 refcount, test_name, i, expected_refcount);
1712 static void test_surface_qi(void)
1714 static const struct qi_test tests[] =
1716 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1717 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1718 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1719 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1720 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1721 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1722 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1723 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1724 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1725 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1726 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1727 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1728 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1729 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1730 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1731 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1732 {&IID_IDirect3D, NULL, E_INVALIDARG },
1733 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1734 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1735 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1736 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1737 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1738 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1739 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1740 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1741 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1742 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1743 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1744 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1745 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1746 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1747 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1748 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1749 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1750 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1753 IDirectDrawSurface *surface;
1754 DDSURFACEDESC surface_desc;
1755 IDirect3DDevice *device;
1756 IDirectDraw *ddraw;
1757 HWND window;
1758 HRESULT hr;
1760 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1762 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1763 return;
1766 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1767 0, 0, 640, 480, 0, 0, 0, 0);
1768 ddraw = create_ddraw();
1769 ok(!!ddraw, "Failed to create a ddraw object.\n");
1770 /* Try to create a D3D device to see if the ddraw implementation supports
1771 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1772 * doesn't support e.g. the IDirect3DTexture interfaces. */
1773 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1775 skip("Failed to create a 3D device, skipping test.\n");
1776 IDirectDraw_Release(ddraw);
1777 DestroyWindow(window);
1778 return;
1780 IDirect3DDevice_Release(device);
1782 memset(&surface_desc, 0, sizeof(surface_desc));
1783 surface_desc.dwSize = sizeof(surface_desc);
1784 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1785 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1786 surface_desc.dwWidth = 512;
1787 surface_desc.dwHeight = 512;
1788 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1789 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1791 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1793 IDirectDrawSurface_Release(surface);
1794 IDirectDraw_Release(ddraw);
1795 DestroyWindow(window);
1798 static void test_device_qi(void)
1800 static const struct qi_test tests[] =
1802 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1803 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1804 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1805 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1806 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1807 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1808 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1809 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1810 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1811 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1812 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1813 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1814 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1815 {&IID_IDirect3DHALDevice, &IID_IDirectDrawSurface, S_OK },
1816 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1817 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1818 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1819 {&IID_IDirect3D, NULL, E_INVALIDARG },
1820 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1821 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1822 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1823 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1824 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1825 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1826 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1827 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1828 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1829 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1830 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1831 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1832 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1833 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1834 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1835 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1836 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1837 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1841 IDirect3DDevice *device;
1842 IDirectDraw *ddraw;
1843 HWND window;
1845 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1847 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1848 return;
1851 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1852 0, 0, 640, 480, 0, 0, 0, 0);
1853 ddraw = create_ddraw();
1854 ok(!!ddraw, "Failed to create a ddraw object.\n");
1855 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1857 skip("Failed to create a 3D device, skipping test.\n");
1858 IDirectDraw_Release(ddraw);
1859 DestroyWindow(window);
1860 return;
1863 test_qi("device_qi", (IUnknown *)device, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1865 IDirect3DDevice_Release(device);
1866 IDirectDraw_Release(ddraw);
1867 DestroyWindow(window);
1870 static void test_wndproc(void)
1872 LONG_PTR proc, ddraw_proc;
1873 IDirectDraw *ddraw;
1874 WNDCLASSA wc = {0};
1875 HWND window;
1876 HRESULT hr;
1877 ULONG ref;
1879 static const UINT messages[] =
1881 WM_WINDOWPOSCHANGING,
1882 WM_MOVE,
1883 WM_SIZE,
1884 WM_WINDOWPOSCHANGING,
1885 WM_ACTIVATE,
1886 WM_SETFOCUS,
1890 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
1891 ddraw = create_ddraw();
1892 ok(!!ddraw, "Failed to create a ddraw object.\n");
1894 wc.lpfnWndProc = test_proc;
1895 wc.lpszClassName = "ddraw_test_wndproc_wc";
1896 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1898 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
1899 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
1901 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1902 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1903 (LONG_PTR)test_proc, proc);
1904 expect_messages = messages;
1905 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1906 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1907 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
1908 expect_messages = NULL;
1909 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1910 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1911 (LONG_PTR)test_proc, proc);
1912 ref = IDirectDraw_Release(ddraw);
1913 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1914 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1915 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1916 (LONG_PTR)test_proc, proc);
1918 /* DDSCL_NORMAL doesn't. */
1919 ddraw = create_ddraw();
1920 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1921 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1922 (LONG_PTR)test_proc, proc);
1923 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
1924 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1925 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1926 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1927 (LONG_PTR)test_proc, proc);
1928 ref = IDirectDraw_Release(ddraw);
1929 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1930 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1931 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1932 (LONG_PTR)test_proc, proc);
1934 /* The original window proc is only restored by ddraw if the current
1935 * window proc matches the one ddraw set. This also affects switching
1936 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
1937 ddraw = create_ddraw();
1938 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1939 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1940 (LONG_PTR)test_proc, proc);
1941 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1942 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1943 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1944 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1945 (LONG_PTR)test_proc, proc);
1946 ddraw_proc = proc;
1947 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1948 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1949 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1950 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1951 (LONG_PTR)test_proc, proc);
1952 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1953 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1954 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1955 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1956 (LONG_PTR)test_proc, proc);
1957 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1958 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1959 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1960 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1961 (LONG_PTR)DefWindowProcA, proc);
1962 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1963 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1964 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
1965 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1966 (LONG_PTR)DefWindowProcA, proc);
1967 ref = IDirectDraw_Release(ddraw);
1968 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1969 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1970 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1971 (LONG_PTR)test_proc, proc);
1973 ddraw = create_ddraw();
1974 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1975 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1976 (LONG_PTR)test_proc, proc);
1977 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1978 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1979 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1980 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1981 (LONG_PTR)test_proc, proc);
1982 ref = IDirectDraw_Release(ddraw);
1983 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1984 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1985 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1986 (LONG_PTR)DefWindowProcA, proc);
1988 fix_wndproc(window, (LONG_PTR)test_proc);
1989 expect_messages = NULL;
1990 DestroyWindow(window);
1991 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
1994 static void test_window_style(void)
1996 LONG style, exstyle, tmp;
1997 RECT fullscreen_rect, r;
1998 IDirectDraw *ddraw;
1999 HWND window;
2000 HRESULT hr;
2001 ULONG ref;
2003 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2004 0, 0, 100, 100, 0, 0, 0, 0);
2005 ddraw = create_ddraw();
2006 ok(!!ddraw, "Failed to create a ddraw object.\n");
2008 style = GetWindowLongA(window, GWL_STYLE);
2009 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2010 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2012 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2013 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2015 tmp = GetWindowLongA(window, GWL_STYLE);
2016 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2017 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2018 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2020 GetWindowRect(window, &r);
2021 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2022 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2023 r.left, r.top, r.right, r.bottom);
2024 GetClientRect(window, &r);
2025 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2027 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2028 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2030 tmp = GetWindowLongA(window, GWL_STYLE);
2031 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2032 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2033 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2035 ref = IDirectDraw_Release(ddraw);
2036 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2038 DestroyWindow(window);
2041 static void test_redundant_mode_set(void)
2043 DDSURFACEDESC surface_desc = {0};
2044 IDirectDraw *ddraw;
2045 HWND window;
2046 HRESULT hr;
2047 RECT r, s;
2048 ULONG ref;
2050 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2051 0, 0, 100, 100, 0, 0, 0, 0);
2052 ddraw = create_ddraw();
2053 ok(!!ddraw, "Failed to create a ddraw object.\n");
2055 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2056 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2058 surface_desc.dwSize = sizeof(surface_desc);
2059 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
2060 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
2062 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2063 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
2064 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2066 GetWindowRect(window, &r);
2067 r.right /= 2;
2068 r.bottom /= 2;
2069 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2070 GetWindowRect(window, &s);
2071 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2072 r.left, r.top, r.right, r.bottom,
2073 s.left, s.top, s.right, s.bottom);
2075 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2076 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
2077 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2079 GetWindowRect(window, &s);
2080 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2081 r.left, r.top, r.right, r.bottom,
2082 s.left, s.top, s.right, s.bottom);
2084 ref = IDirectDraw_Release(ddraw);
2085 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2087 DestroyWindow(window);
2090 static SIZE screen_size;
2092 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2094 if (message == WM_SIZE)
2096 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2097 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2100 return test_proc(hwnd, message, wparam, lparam);
2103 static void test_coop_level_mode_set(void)
2105 IDirectDrawSurface *primary;
2106 RECT fullscreen_rect, r, s;
2107 IDirectDraw *ddraw;
2108 DDSURFACEDESC ddsd;
2109 WNDCLASSA wc = {0};
2110 HWND window;
2111 HRESULT hr;
2112 ULONG ref;
2113 MSG msg;
2115 static const UINT exclusive_messages[] =
2117 WM_WINDOWPOSCHANGING,
2118 WM_WINDOWPOSCHANGED,
2119 WM_SIZE,
2120 WM_DISPLAYCHANGE,
2124 static const UINT normal_messages[] =
2126 WM_DISPLAYCHANGE,
2130 ddraw = create_ddraw();
2131 ok(!!ddraw, "Failed to create a ddraw object.\n");
2133 wc.lpfnWndProc = mode_set_proc;
2134 wc.lpszClassName = "ddraw_test_wndproc_wc";
2135 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2137 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2138 0, 0, 100, 100, 0, 0, 0, 0);
2140 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2141 SetRect(&s, 0, 0, 640, 480);
2143 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2144 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2146 GetWindowRect(window, &r);
2147 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2148 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2149 r.left, r.top, r.right, r.bottom);
2151 memset(&ddsd, 0, sizeof(ddsd));
2152 ddsd.dwSize = sizeof(ddsd);
2153 ddsd.dwFlags = DDSD_CAPS;
2154 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2156 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2157 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2158 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2159 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2160 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2161 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2162 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2163 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2165 GetWindowRect(window, &r);
2166 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2167 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2168 r.left, r.top, r.right, r.bottom);
2170 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2171 expect_messages = exclusive_messages;
2172 screen_size.cx = 0;
2173 screen_size.cy = 0;
2175 hr = set_display_mode(ddraw, 640, 480);
2176 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2178 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2179 expect_messages = NULL;
2180 ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
2181 "Expected screen size %ux%u, got %ux%u.\n",
2182 s.right, s.bottom, screen_size.cx, screen_size.cy);
2184 GetWindowRect(window, &r);
2185 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2186 s.left, s.top, s.right, s.bottom,
2187 r.left, r.top, r.right, r.bottom);
2189 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2190 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2191 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2192 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2193 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2194 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2195 IDirectDrawSurface_Release(primary);
2197 memset(&ddsd, 0, sizeof(ddsd));
2198 ddsd.dwSize = sizeof(ddsd);
2199 ddsd.dwFlags = DDSD_CAPS;
2200 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2202 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2203 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2204 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2205 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2206 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2207 s.right - s.left, ddsd.dwWidth);
2208 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2209 s.bottom - s.top, ddsd.dwHeight);
2211 GetWindowRect(window, &r);
2212 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2213 s.left, s.top, s.right, s.bottom,
2214 r.left, r.top, r.right, r.bottom);
2216 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2217 expect_messages = exclusive_messages;
2218 screen_size.cx = 0;
2219 screen_size.cy = 0;
2221 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2222 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2224 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2225 expect_messages = NULL;
2226 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2227 "Expected screen size %ux%u, got %ux%u.\n",
2228 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2230 GetWindowRect(window, &r);
2231 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2232 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2233 r.left, r.top, r.right, r.bottom);
2235 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2236 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2237 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2238 s.right - s.left, ddsd.dwWidth);
2239 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2240 s.bottom - s.top, ddsd.dwHeight);
2241 IDirectDrawSurface_Release(primary);
2243 memset(&ddsd, 0, sizeof(ddsd));
2244 ddsd.dwSize = sizeof(ddsd);
2245 ddsd.dwFlags = DDSD_CAPS;
2246 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2248 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2249 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2250 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2251 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2252 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2253 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2254 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2255 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2257 GetWindowRect(window, &r);
2258 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2259 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2260 r.left, r.top, r.right, r.bottom);
2262 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2263 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2265 GetWindowRect(window, &r);
2266 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2267 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2268 r.left, r.top, r.right, r.bottom);
2270 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2271 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2272 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2273 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2274 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2275 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2276 IDirectDrawSurface_Release(primary);
2278 memset(&ddsd, 0, sizeof(ddsd));
2279 ddsd.dwSize = sizeof(ddsd);
2280 ddsd.dwFlags = DDSD_CAPS;
2281 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2283 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2284 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2285 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2286 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2287 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2288 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2289 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2290 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2292 GetWindowRect(window, &r);
2293 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2294 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2295 r.left, r.top, r.right, r.bottom);
2297 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2298 expect_messages = normal_messages;
2299 screen_size.cx = 0;
2300 screen_size.cy = 0;
2302 hr = set_display_mode(ddraw, 640, 480);
2303 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
2305 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
2306 IDirectDrawSurface_Release(primary);
2307 IDirectDraw_Release(ddraw);
2308 goto done;
2310 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2312 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2313 expect_messages = NULL;
2314 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2316 GetWindowRect(window, &r);
2317 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2318 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2319 r.left, r.top, r.right, r.bottom);
2321 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2322 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2323 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2324 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2325 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2326 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2327 IDirectDrawSurface_Release(primary);
2329 memset(&ddsd, 0, sizeof(ddsd));
2330 ddsd.dwSize = sizeof(ddsd);
2331 ddsd.dwFlags = DDSD_CAPS;
2332 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2334 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2335 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2336 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2337 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2338 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2339 s.right - s.left, ddsd.dwWidth);
2340 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2341 s.bottom - s.top, ddsd.dwHeight);
2343 GetWindowRect(window, &r);
2344 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2345 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2346 r.left, r.top, r.right, r.bottom);
2348 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2349 expect_messages = normal_messages;
2350 screen_size.cx = 0;
2351 screen_size.cy = 0;
2353 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2354 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2356 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2357 expect_messages = NULL;
2358 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2360 GetWindowRect(window, &r);
2361 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2362 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2363 r.left, r.top, r.right, r.bottom);
2365 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2366 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2367 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2368 s.right - s.left, ddsd.dwWidth);
2369 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2370 s.bottom - s.top, ddsd.dwHeight);
2371 IDirectDrawSurface_Release(primary);
2373 memset(&ddsd, 0, sizeof(ddsd));
2374 ddsd.dwSize = sizeof(ddsd);
2375 ddsd.dwFlags = DDSD_CAPS;
2376 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2378 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2379 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2380 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2381 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2382 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2383 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2384 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2385 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2387 GetWindowRect(window, &r);
2388 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2389 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2390 r.left, r.top, r.right, r.bottom);
2392 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2393 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2394 * not DDSCL_FULLSCREEN. */
2395 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2396 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2398 GetWindowRect(window, &r);
2399 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2400 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2401 r.left, r.top, r.right, r.bottom);
2403 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2404 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2405 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2406 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2407 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2408 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2409 IDirectDrawSurface_Release(primary);
2411 memset(&ddsd, 0, sizeof(ddsd));
2412 ddsd.dwSize = sizeof(ddsd);
2413 ddsd.dwFlags = DDSD_CAPS;
2414 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2416 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2417 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2418 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2419 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2420 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2421 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2422 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2423 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2425 GetWindowRect(window, &r);
2426 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2427 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2428 r.left, r.top, r.right, r.bottom);
2430 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2431 expect_messages = normal_messages;
2432 screen_size.cx = 0;
2433 screen_size.cy = 0;
2435 hr = set_display_mode(ddraw, 640, 480);
2436 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2438 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2439 expect_messages = NULL;
2440 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2442 GetWindowRect(window, &r);
2443 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2444 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2445 r.left, r.top, r.right, r.bottom);
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 memset(&ddsd, 0, sizeof(ddsd));
2456 ddsd.dwSize = sizeof(ddsd);
2457 ddsd.dwFlags = DDSD_CAPS;
2458 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2460 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2461 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2462 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2463 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2464 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2465 s.right - s.left, ddsd.dwWidth);
2466 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2467 s.bottom - s.top, ddsd.dwHeight);
2469 GetWindowRect(window, &r);
2470 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2471 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2472 r.left, r.top, r.right, r.bottom);
2474 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2475 expect_messages = normal_messages;
2476 screen_size.cx = 0;
2477 screen_size.cy = 0;
2479 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2480 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2482 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2483 expect_messages = NULL;
2484 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2486 GetWindowRect(window, &r);
2487 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2488 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2489 r.left, r.top, r.right, r.bottom);
2491 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2492 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2493 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2494 s.right - s.left, ddsd.dwWidth);
2495 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2496 s.bottom - s.top, ddsd.dwHeight);
2497 IDirectDrawSurface_Release(primary);
2499 memset(&ddsd, 0, sizeof(ddsd));
2500 ddsd.dwSize = sizeof(ddsd);
2501 ddsd.dwFlags = DDSD_CAPS;
2502 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2504 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2505 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2506 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2507 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2508 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2509 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2510 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2511 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2512 IDirectDrawSurface_Release(primary);
2514 GetWindowRect(window, &r);
2515 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2516 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2517 r.left, r.top, r.right, r.bottom);
2519 /* Unlike ddraw2-7, changing from EXCLUSIVE to NORMAL does not restore the resolution */
2520 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2521 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2522 hr = set_display_mode(ddraw, 640, 480);
2523 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2525 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2526 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2528 memset(&ddsd, 0, sizeof(ddsd));
2529 ddsd.dwSize = sizeof(ddsd);
2530 ddsd.dwFlags = DDSD_CAPS;
2531 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2533 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2534 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2535 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2536 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2537 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2538 s.right - s.left, ddsd.dwWidth);
2539 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2540 s.bottom - s.top, ddsd.dwHeight);
2541 IDirectDrawSurface_Release(primary);
2542 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2543 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2545 ref = IDirectDraw_Release(ddraw);
2546 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2548 GetWindowRect(window, &r);
2549 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2550 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2551 r.left, r.top, r.right, r.bottom);
2553 done:
2554 expect_messages = NULL;
2555 DestroyWindow(window);
2556 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2559 static void test_coop_level_mode_set_multi(void)
2561 IDirectDraw *ddraw1, *ddraw2;
2562 UINT orig_w, orig_h, w, h;
2563 HWND window;
2564 HRESULT hr;
2565 ULONG ref;
2567 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2568 0, 0, 100, 100, 0, 0, 0, 0);
2569 ddraw1 = create_ddraw();
2570 ok(!!ddraw1, "Failed to create a ddraw object.\n");
2572 orig_w = GetSystemMetrics(SM_CXSCREEN);
2573 orig_h = GetSystemMetrics(SM_CYSCREEN);
2575 /* With just a single ddraw object, the display mode is restored on
2576 * release. */
2577 hr = set_display_mode(ddraw1, 800, 600);
2578 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
2580 win_skip("Broken SetDisplayMode(), skipping test.\n");
2581 IDirectDraw_Release(ddraw1);
2582 DestroyWindow(window);
2583 return;
2585 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2586 w = GetSystemMetrics(SM_CXSCREEN);
2587 ok(w == 800, "Got unexpected screen width %u.\n", w);
2588 h = GetSystemMetrics(SM_CYSCREEN);
2589 ok(h == 600, "Got unexpected screen height %u.\n", h);
2591 ref = IDirectDraw_Release(ddraw1);
2592 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2593 w = GetSystemMetrics(SM_CXSCREEN);
2594 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2595 h = GetSystemMetrics(SM_CYSCREEN);
2596 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2598 /* When there are multiple ddraw objects, the display mode is restored to
2599 * the initial mode, before the first SetDisplayMode() call. */
2600 ddraw1 = create_ddraw();
2601 hr = set_display_mode(ddraw1, 800, 600);
2602 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2603 w = GetSystemMetrics(SM_CXSCREEN);
2604 ok(w == 800, "Got unexpected screen width %u.\n", w);
2605 h = GetSystemMetrics(SM_CYSCREEN);
2606 ok(h == 600, "Got unexpected screen height %u.\n", h);
2608 ddraw2 = create_ddraw();
2609 hr = set_display_mode(ddraw2, 640, 480);
2610 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2611 w = GetSystemMetrics(SM_CXSCREEN);
2612 ok(w == 640, "Got unexpected screen width %u.\n", w);
2613 h = GetSystemMetrics(SM_CYSCREEN);
2614 ok(h == 480, "Got unexpected screen height %u.\n", h);
2616 ref = IDirectDraw_Release(ddraw2);
2617 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2618 w = GetSystemMetrics(SM_CXSCREEN);
2619 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2620 h = GetSystemMetrics(SM_CYSCREEN);
2621 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2623 ref = IDirectDraw_Release(ddraw1);
2624 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2625 w = GetSystemMetrics(SM_CXSCREEN);
2626 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2627 h = GetSystemMetrics(SM_CYSCREEN);
2628 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2630 /* Regardless of release ordering. */
2631 ddraw1 = create_ddraw();
2632 hr = set_display_mode(ddraw1, 800, 600);
2633 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2634 w = GetSystemMetrics(SM_CXSCREEN);
2635 ok(w == 800, "Got unexpected screen width %u.\n", w);
2636 h = GetSystemMetrics(SM_CYSCREEN);
2637 ok(h == 600, "Got unexpected screen height %u.\n", h);
2639 ddraw2 = create_ddraw();
2640 hr = set_display_mode(ddraw2, 640, 480);
2641 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2642 w = GetSystemMetrics(SM_CXSCREEN);
2643 ok(w == 640, "Got unexpected screen width %u.\n", w);
2644 h = GetSystemMetrics(SM_CYSCREEN);
2645 ok(h == 480, "Got unexpected screen height %u.\n", h);
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 == orig_w, "Got unexpected screen width %u.\n", w);
2651 h = GetSystemMetrics(SM_CYSCREEN);
2652 ok(h == orig_h, "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 /* But only for ddraw objects that called SetDisplayMode(). */
2662 ddraw1 = create_ddraw();
2663 ddraw2 = create_ddraw();
2664 hr = set_display_mode(ddraw2, 640, 480);
2665 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2666 w = GetSystemMetrics(SM_CXSCREEN);
2667 ok(w == 640, "Got unexpected screen width %u.\n", w);
2668 h = GetSystemMetrics(SM_CYSCREEN);
2669 ok(h == 480, "Got unexpected screen height %u.\n", h);
2671 ref = IDirectDraw_Release(ddraw1);
2672 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2673 w = GetSystemMetrics(SM_CXSCREEN);
2674 ok(w == 640, "Got unexpected screen width %u.\n", w);
2675 h = GetSystemMetrics(SM_CYSCREEN);
2676 ok(h == 480, "Got unexpected screen height %u.\n", h);
2678 ref = IDirectDraw_Release(ddraw2);
2679 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2680 w = GetSystemMetrics(SM_CXSCREEN);
2681 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2682 h = GetSystemMetrics(SM_CYSCREEN);
2683 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2685 /* If there's a ddraw object that's currently in exclusive mode, it blocks
2686 * restoring the display mode. */
2687 ddraw1 = create_ddraw();
2688 hr = set_display_mode(ddraw1, 800, 600);
2689 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2690 w = GetSystemMetrics(SM_CXSCREEN);
2691 ok(w == 800, "Got unexpected screen width %u.\n", w);
2692 h = GetSystemMetrics(SM_CYSCREEN);
2693 ok(h == 600, "Got unexpected screen height %u.\n", h);
2695 ddraw2 = create_ddraw();
2696 hr = set_display_mode(ddraw2, 640, 480);
2697 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2698 w = GetSystemMetrics(SM_CXSCREEN);
2699 ok(w == 640, "Got unexpected screen width %u.\n", w);
2700 h = GetSystemMetrics(SM_CYSCREEN);
2701 ok(h == 480, "Got unexpected screen height %u.\n", h);
2703 hr = IDirectDraw_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2704 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2706 ref = IDirectDraw_Release(ddraw1);
2707 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2708 w = GetSystemMetrics(SM_CXSCREEN);
2709 ok(w == 640, "Got unexpected screen width %u.\n", w);
2710 h = GetSystemMetrics(SM_CYSCREEN);
2711 ok(h == 480, "Got unexpected screen height %u.\n", h);
2713 ref = IDirectDraw_Release(ddraw2);
2714 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2715 w = GetSystemMetrics(SM_CXSCREEN);
2716 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2717 h = GetSystemMetrics(SM_CYSCREEN);
2718 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2720 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
2721 ddraw1 = create_ddraw();
2722 hr = set_display_mode(ddraw1, 800, 600);
2723 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2724 w = GetSystemMetrics(SM_CXSCREEN);
2725 ok(w == 800, "Got unexpected screen width %u.\n", w);
2726 h = GetSystemMetrics(SM_CYSCREEN);
2727 ok(h == 600, "Got unexpected screen height %u.\n", h);
2729 hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2730 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2732 ddraw2 = create_ddraw();
2733 hr = set_display_mode(ddraw2, 640, 480);
2734 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
2736 ref = IDirectDraw_Release(ddraw1);
2737 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2738 w = GetSystemMetrics(SM_CXSCREEN);
2739 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2740 h = GetSystemMetrics(SM_CYSCREEN);
2741 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2743 ref = IDirectDraw_Release(ddraw2);
2744 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2745 w = GetSystemMetrics(SM_CXSCREEN);
2746 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2747 h = GetSystemMetrics(SM_CYSCREEN);
2748 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2750 DestroyWindow(window);
2753 static void test_initialize(void)
2755 IDirectDraw *ddraw;
2756 IDirect3D *d3d;
2757 HRESULT hr;
2759 ddraw = create_ddraw();
2760 ok(!!ddraw, "Failed to create a ddraw object.\n");
2762 hr = IDirectDraw_Initialize(ddraw, NULL);
2763 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
2764 IDirectDraw_Release(ddraw);
2766 CoInitialize(NULL);
2767 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw);
2768 ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
2769 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
2770 if (SUCCEEDED(hr))
2772 /* IDirect3D_Initialize() just returns DDERR_ALREADYINITIALIZED. */
2773 hr = IDirect3D_Initialize(d3d, NULL);
2774 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2775 IDirect3D_Release(d3d);
2777 else
2778 skip("D3D interface is not available, skipping test.\n");
2779 hr = IDirectDraw_Initialize(ddraw, NULL);
2780 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
2781 hr = IDirectDraw_Initialize(ddraw, NULL);
2782 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2783 IDirectDraw_Release(ddraw);
2784 CoUninitialize();
2786 if (0) /* This crashes on the W2KPROSP4 testbot. */
2788 CoInitialize(NULL);
2789 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d);
2790 ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#x, expected E_NOINTERFACE.\n", hr);
2791 CoUninitialize();
2795 static void test_coop_level_surf_create(void)
2797 IDirectDrawSurface *surface;
2798 IDirectDraw *ddraw;
2799 DDSURFACEDESC ddsd;
2800 HRESULT hr;
2802 ddraw = create_ddraw();
2803 ok(!!ddraw, "Failed to create a ddraw object.\n");
2805 memset(&ddsd, 0, sizeof(ddsd));
2806 ddsd.dwSize = sizeof(ddsd);
2807 ddsd.dwFlags = DDSD_CAPS;
2808 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2809 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
2810 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
2812 IDirectDraw_Release(ddraw);
2815 static void test_coop_level_multi_window(void)
2817 HWND window1, window2;
2818 IDirectDraw *ddraw;
2819 HRESULT hr;
2821 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
2822 0, 0, 640, 480, 0, 0, 0, 0);
2823 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
2824 0, 0, 640, 480, 0, 0, 0, 0);
2825 ddraw = create_ddraw();
2826 ok(!!ddraw, "Failed to create a ddraw object.\n");
2828 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
2829 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2830 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
2831 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2832 ok(IsWindow(window1), "Window 1 was destroyed.\n");
2833 ok(IsWindow(window2), "Window 2 was destroyed.\n");
2835 IDirectDraw_Release(ddraw);
2836 DestroyWindow(window2);
2837 DestroyWindow(window1);
2840 static void test_clear_rect_count(void)
2842 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
2843 IDirect3DMaterial *white, *red, *green, *blue;
2844 IDirect3DViewport *viewport;
2845 IDirect3DDevice *device;
2846 IDirectDrawSurface *rt;
2847 IDirectDraw *ddraw;
2848 D3DCOLOR color;
2849 HWND window;
2850 HRESULT hr;
2852 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2853 0, 0, 640, 480, 0, 0, 0, 0);
2854 ddraw = create_ddraw();
2855 ok(!!ddraw, "Failed to create a ddraw object.\n");
2856 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2858 skip("Failed to create a 3D device, skipping test.\n");
2859 IDirectDraw_Release(ddraw);
2860 DestroyWindow(window);
2861 return;
2864 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
2865 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
2867 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
2868 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
2869 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
2870 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
2871 viewport = create_viewport(device, 0, 0, 640, 480);
2873 viewport_set_background(device, viewport, white);
2874 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2875 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2876 viewport_set_background(device, viewport, red);
2877 hr = IDirect3DViewport_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
2878 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2879 viewport_set_background(device, viewport, green);
2880 hr = IDirect3DViewport_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
2881 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2882 viewport_set_background(device, viewport, blue);
2883 hr = IDirect3DViewport_Clear(viewport, 1, NULL, D3DCLEAR_TARGET);
2884 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2886 color = get_surface_color(rt, 320, 240);
2887 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
2889 IDirectDrawSurface_Release(rt);
2890 destroy_viewport(device, viewport);
2891 destroy_material(white);
2892 destroy_material(red);
2893 destroy_material(green);
2894 destroy_material(blue);
2895 IDirect3DDevice_Release(device);
2896 IDirectDraw_Release(ddraw);
2897 DestroyWindow(window);
2900 static struct
2902 BOOL received;
2903 IDirectDraw *ddraw;
2904 HWND window;
2905 DWORD coop_level;
2906 } activateapp_testdata;
2908 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2910 if (message == WM_ACTIVATEAPP)
2912 if (activateapp_testdata.ddraw)
2914 HRESULT hr;
2915 activateapp_testdata.received = FALSE;
2916 hr = IDirectDraw_SetCooperativeLevel(activateapp_testdata.ddraw,
2917 activateapp_testdata.window, activateapp_testdata.coop_level);
2918 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
2919 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
2921 activateapp_testdata.received = TRUE;
2924 return DefWindowProcA(hwnd, message, wparam, lparam);
2927 static void test_coop_level_activateapp(void)
2929 IDirectDraw *ddraw;
2930 HRESULT hr;
2931 HWND window;
2932 WNDCLASSA wc = {0};
2933 DDSURFACEDESC ddsd;
2934 IDirectDrawSurface *surface;
2936 ddraw = create_ddraw();
2937 ok(!!ddraw, "Failed to create a ddraw object.\n");
2939 wc.lpfnWndProc = activateapp_test_proc;
2940 wc.lpszClassName = "ddraw_test_wndproc_wc";
2941 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2943 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2944 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2946 /* Exclusive with window already active. */
2947 SetActiveWindow(window);
2948 activateapp_testdata.received = FALSE;
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, "Received WM_ACTIVATEAPP although window was already active.\n");
2952 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2953 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2955 /* Exclusive with window not active. */
2956 SetActiveWindow(NULL);
2957 activateapp_testdata.received = FALSE;
2958 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2959 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2960 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
2961 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2962 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2964 /* Normal with window not active, then exclusive with the same window. */
2965 SetActiveWindow(NULL);
2966 activateapp_testdata.received = FALSE;
2967 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2968 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2969 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
2970 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2971 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2972 /* Except in the first SetCooperativeLevel call, Windows XP randomly does not send
2973 * WM_ACTIVATEAPP. Windows 7 sends the message reliably. Mark the XP behavior broken. */
2974 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
2975 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
2976 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2977 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2979 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
2980 SetActiveWindow(NULL);
2981 activateapp_testdata.received = FALSE;
2982 activateapp_testdata.ddraw = ddraw;
2983 activateapp_testdata.window = window;
2984 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
2985 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2986 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2987 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
2988 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
2989 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2990 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2992 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
2993 * succeeding. Another switch to exclusive and back to normal is needed to release the
2994 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
2995 * WM_ACTIVATEAPP messages. */
2996 activateapp_testdata.ddraw = NULL;
2997 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2998 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2999 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3000 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3002 /* Setting DDSCL_NORMAL with recursive invocation. */
3003 SetActiveWindow(NULL);
3004 activateapp_testdata.received = FALSE;
3005 activateapp_testdata.ddraw = ddraw;
3006 activateapp_testdata.window = window;
3007 activateapp_testdata.coop_level = DDSCL_NORMAL;
3008 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3009 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3010 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
3011 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3013 /* DDraw is in exlusive mode now. */
3014 memset(&ddsd, 0, sizeof(ddsd));
3015 ddsd.dwSize = sizeof(ddsd);
3016 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
3017 ddsd.dwBackBufferCount = 1;
3018 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
3019 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3020 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3021 IDirectDrawSurface_Release(surface);
3023 /* Recover again, just to be sure. */
3024 activateapp_testdata.ddraw = NULL;
3025 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3026 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3027 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3028 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3030 DestroyWindow(window);
3031 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3032 IDirectDraw_Release(ddraw);
3035 struct format_support_check
3037 const DDPIXELFORMAT *format;
3038 BOOL supported;
3041 static HRESULT WINAPI test_unsupported_formats_cb(DDSURFACEDESC *desc, void *ctx)
3043 struct format_support_check *format = ctx;
3045 if (!memcmp(format->format, &desc->ddpfPixelFormat, sizeof(*format->format)))
3047 format->supported = TRUE;
3048 return DDENUMRET_CANCEL;
3051 return DDENUMRET_OK;
3054 static void test_unsupported_formats(void)
3056 HRESULT hr;
3057 BOOL expect_success;
3058 HWND window;
3059 IDirectDraw *ddraw;
3060 IDirect3DDevice *device;
3061 IDirectDrawSurface *surface;
3062 DDSURFACEDESC ddsd;
3063 unsigned int i, j;
3064 DWORD expected_caps;
3065 static const struct
3067 const char *name;
3068 DDPIXELFORMAT fmt;
3070 formats[] =
3073 "D3DFMT_A8R8G8B8",
3075 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3076 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
3080 "D3DFMT_P8",
3082 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3083 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3087 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
3089 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3090 0, 0, 640, 480, 0, 0, 0, 0);
3091 ddraw = create_ddraw();
3092 ok(!!ddraw, "Failed to create a ddraw object.\n");
3093 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3095 skip("Failed to create a 3D device, skipping test.\n");
3096 IDirectDraw_Release(ddraw);
3097 DestroyWindow(window);
3098 return;
3101 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
3103 struct format_support_check check = {&formats[i].fmt, FALSE};
3104 hr = IDirect3DDevice_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
3105 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
3107 for (j = 0; j < sizeof(caps) / sizeof(*caps); j++)
3109 memset(&ddsd, 0, sizeof(ddsd));
3110 ddsd.dwSize = sizeof(ddsd);
3111 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3112 ddsd.ddpfPixelFormat = formats[i].fmt;
3113 ddsd.dwWidth = 4;
3114 ddsd.dwHeight = 4;
3115 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
3117 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
3118 expect_success = FALSE;
3119 else
3120 expect_success = TRUE;
3122 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3123 ok(SUCCEEDED(hr) == expect_success,
3124 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
3125 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
3126 if (FAILED(hr))
3127 continue;
3129 memset(&ddsd, 0, sizeof(ddsd));
3130 ddsd.dwSize = sizeof(ddsd);
3131 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
3132 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3134 if (caps[j] & DDSCAPS_VIDEOMEMORY)
3135 expected_caps = DDSCAPS_VIDEOMEMORY;
3136 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
3137 expected_caps = DDSCAPS_SYSTEMMEMORY;
3138 else if (check.supported)
3139 expected_caps = DDSCAPS_VIDEOMEMORY;
3140 else
3141 expected_caps = DDSCAPS_SYSTEMMEMORY;
3143 ok(ddsd.ddsCaps.dwCaps & expected_caps,
3144 "Expected capability %#x, format %s, input cap %#x.\n",
3145 expected_caps, formats[i].name, caps[j]);
3147 IDirectDrawSurface_Release(surface);
3151 IDirect3DDevice_Release(device);
3152 IDirectDraw_Release(ddraw);
3153 DestroyWindow(window);
3156 static void test_rt_caps(void)
3158 PALETTEENTRY palette_entries[256];
3159 IDirectDrawPalette *palette;
3160 IDirect3DDevice *device;
3161 IDirectDraw *ddraw;
3162 DWORD z_depth = 0;
3163 unsigned int i;
3164 ULONG refcount;
3165 HWND window;
3166 HRESULT hr;
3168 static const DDPIXELFORMAT p8_fmt =
3170 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3171 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
3174 static const struct
3176 const DDPIXELFORMAT *pf;
3177 DWORD caps_in;
3178 DWORD caps_out;
3179 HRESULT create_device_hr;
3180 BOOL create_may_fail;
3182 test_data[] =
3185 NULL,
3186 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3187 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3188 D3D_OK,
3189 FALSE,
3192 NULL,
3193 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3194 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3195 D3D_OK,
3196 FALSE,
3199 NULL,
3200 DDSCAPS_OFFSCREENPLAIN,
3201 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3202 DDERR_INVALIDCAPS,
3203 FALSE,
3206 NULL,
3207 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3208 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3209 D3DERR_SURFACENOTINVIDMEM,
3210 FALSE,
3213 NULL,
3214 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3215 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3216 DDERR_INVALIDCAPS,
3217 FALSE,
3220 NULL,
3221 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3222 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3223 D3D_OK,
3224 FALSE,
3227 NULL,
3228 DDSCAPS_3DDEVICE,
3229 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3230 D3D_OK,
3231 FALSE,
3234 NULL,
3236 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3237 DDERR_INVALIDCAPS,
3238 FALSE,
3241 NULL,
3242 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3243 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3244 D3DERR_SURFACENOTINVIDMEM,
3245 FALSE,
3248 NULL,
3249 DDSCAPS_SYSTEMMEMORY,
3250 DDSCAPS_SYSTEMMEMORY,
3251 DDERR_INVALIDCAPS,
3252 FALSE,
3255 &p8_fmt,
3257 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3258 DDERR_INVALIDCAPS,
3259 FALSE,
3262 &p8_fmt,
3263 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3264 ~0U /* AMD r200 */ ,
3265 DDERR_NOPALETTEATTACHED,
3266 FALSE,
3269 &p8_fmt,
3270 DDSCAPS_OFFSCREENPLAIN,
3271 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3272 DDERR_INVALIDCAPS,
3273 FALSE,
3276 &p8_fmt,
3277 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3278 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3279 DDERR_NOPALETTEATTACHED,
3280 FALSE,
3283 &p8_fmt,
3284 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3285 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3286 DDERR_INVALIDCAPS,
3287 FALSE,
3290 NULL,
3291 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
3292 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
3293 DDERR_INVALIDCAPS,
3294 TRUE /* AMD Evergreen */,
3297 NULL,
3298 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3299 ~0U /* AMD Evergreen */,
3300 DDERR_INVALIDCAPS,
3301 FALSE,
3304 NULL,
3305 DDSCAPS_ZBUFFER,
3306 ~0U /* AMD Evergreen */,
3307 DDERR_INVALIDCAPS,
3308 FALSE,
3311 NULL,
3312 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3313 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3314 DDERR_INVALIDCAPS,
3315 TRUE /* Nvidia Kepler */,
3318 NULL,
3319 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3320 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3321 DDERR_INVALIDCAPS,
3322 TRUE /* Nvidia Kepler */,
3326 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3327 0, 0, 640, 480, 0, 0, 0, 0);
3328 ddraw = create_ddraw();
3329 ok(!!ddraw, "Failed to create a ddraw object.\n");
3330 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3332 skip("Failed to create a 3D device, skipping test.\n");
3333 IDirectDraw_Release(ddraw);
3334 DestroyWindow(window);
3335 return;
3337 z_depth = get_device_z_depth(device);
3338 ok(!!z_depth, "Failed to get device z depth.\n");
3339 IDirect3DDevice_Release(device);
3341 memset(palette_entries, 0, sizeof(palette_entries));
3342 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
3343 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
3345 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
3347 IDirectDrawSurface *surface;
3348 DDSURFACEDESC surface_desc;
3349 IDirect3DDevice *device;
3351 memset(&surface_desc, 0, sizeof(surface_desc));
3352 surface_desc.dwSize = sizeof(surface_desc);
3353 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3354 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
3355 if (test_data[i].pf)
3357 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
3358 surface_desc.ddpfPixelFormat = *test_data[i].pf;
3360 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
3362 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
3363 U2(surface_desc).dwZBufferBitDepth = z_depth;
3365 surface_desc.dwWidth = 640;
3366 surface_desc.dwHeight = 480;
3367 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3368 ok(SUCCEEDED(hr) || broken(test_data[i].create_may_fail),
3369 "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
3370 i, test_data[i].caps_in, hr);
3371 if (FAILED(hr))
3372 continue;
3374 memset(&surface_desc, 0, sizeof(surface_desc));
3375 surface_desc.dwSize = sizeof(surface_desc);
3376 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
3377 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
3378 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
3379 "Test %u: Got unexpected caps %#x, expected %#x.\n",
3380 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
3382 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
3383 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
3384 i, hr, test_data[i].create_device_hr);
3385 if (hr == DDERR_NOPALETTEATTACHED)
3387 hr = IDirectDrawSurface_SetPalette(surface, palette);
3388 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
3389 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
3390 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
3391 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
3392 else
3393 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
3395 if (SUCCEEDED(hr))
3397 refcount = IDirect3DDevice_Release(device);
3398 ok(refcount == 1, "Test %u: Got unexpected refcount %u.\n", i, refcount);
3401 refcount = IDirectDrawSurface_Release(surface);
3402 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
3405 IDirectDrawPalette_Release(palette);
3406 refcount = IDirectDraw_Release(ddraw);
3407 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3408 DestroyWindow(window);
3411 static void test_primary_caps(void)
3413 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
3414 IDirectDrawSurface *surface;
3415 DDSURFACEDESC surface_desc;
3416 IDirectDraw *ddraw;
3417 unsigned int i;
3418 ULONG refcount;
3419 HWND window;
3420 HRESULT hr;
3422 static const struct
3424 DWORD coop_level;
3425 DWORD caps_in;
3426 DWORD back_buffer_count;
3427 HRESULT hr;
3428 DWORD caps_out;
3430 test_data[] =
3433 DDSCL_NORMAL,
3434 DDSCAPS_PRIMARYSURFACE,
3435 ~0u,
3436 DD_OK,
3437 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
3440 DDSCL_NORMAL,
3441 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
3442 ~0u,
3443 DDERR_INVALIDCAPS,
3444 ~0u,
3447 DDSCL_NORMAL,
3448 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
3449 ~0u,
3450 DD_OK,
3451 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
3454 DDSCL_NORMAL,
3455 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
3456 ~0u,
3457 DDERR_INVALIDCAPS,
3458 ~0u,
3461 DDSCL_NORMAL,
3462 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
3463 ~0u,
3464 DDERR_INVALIDCAPS,
3465 ~0u,
3468 DDSCL_NORMAL,
3469 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
3470 ~0u,
3471 DDERR_INVALIDCAPS,
3472 ~0u,
3475 DDSCL_NORMAL,
3476 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3477 ~0u,
3478 DDERR_INVALIDCAPS,
3479 ~0u,
3482 DDSCL_NORMAL,
3483 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3485 DDERR_INVALIDCAPS,
3486 ~0u,
3489 DDSCL_NORMAL,
3490 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3492 DDERR_NOEXCLUSIVEMODE,
3493 ~0u,
3496 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3497 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3499 DDERR_INVALIDCAPS,
3500 ~0u,
3503 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3504 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3506 DD_OK,
3507 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
3510 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3511 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
3513 DDERR_INVALIDCAPS,
3514 ~0u,
3517 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3518 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
3520 DDERR_INVALIDCAPS,
3521 ~0u,
3525 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3526 0, 0, 640, 480, 0, 0, 0, 0);
3527 ddraw = create_ddraw();
3528 ok(!!ddraw, "Failed to create a ddraw object.\n");
3530 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
3532 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
3533 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3535 memset(&surface_desc, 0, sizeof(surface_desc));
3536 surface_desc.dwSize = sizeof(surface_desc);
3537 surface_desc.dwFlags = DDSD_CAPS;
3538 if (test_data[i].back_buffer_count != ~0u)
3539 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
3540 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
3541 surface_desc.dwBackBufferCount = test_data[i].back_buffer_count;
3542 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3543 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
3544 if (FAILED(hr))
3545 continue;
3547 memset(&surface_desc, 0, sizeof(surface_desc));
3548 surface_desc.dwSize = sizeof(surface_desc);
3549 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
3550 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
3551 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
3552 "Test %u: Got unexpected caps %#x, expected %#x.\n",
3553 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
3555 IDirectDrawSurface_Release(surface);
3558 refcount = IDirectDraw_Release(ddraw);
3559 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3560 DestroyWindow(window);
3563 static void test_surface_lock(void)
3565 IDirectDraw *ddraw;
3566 IDirectDrawSurface *surface;
3567 IDirect3DDevice *device;
3568 HRESULT hr;
3569 HWND window;
3570 unsigned int i;
3571 DDSURFACEDESC ddsd;
3572 ULONG refcount;
3573 DWORD z_depth = 0;
3574 static const struct
3576 DWORD caps;
3577 const char *name;
3579 tests[] =
3582 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
3583 "videomemory offscreenplain"
3586 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3587 "systemmemory offscreenplain"
3590 DDSCAPS_PRIMARYSURFACE,
3591 "primary"
3594 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
3595 "videomemory texture"
3598 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
3599 "systemmemory texture"
3602 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3603 "render target"
3606 DDSCAPS_ZBUFFER,
3607 "Z buffer"
3611 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3612 0, 0, 640, 480, 0, 0, 0, 0);
3613 ddraw = create_ddraw();
3614 ok(!!ddraw, "Failed to create a ddraw object.\n");
3615 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3617 skip("Failed to create a 3D device, skipping test.\n");
3618 IDirectDraw_Release(ddraw);
3619 DestroyWindow(window);
3620 return;
3622 z_depth = get_device_z_depth(device);
3623 ok(!!z_depth, "Failed to get device z depth.\n");
3624 IDirect3DDevice_Release(device);
3626 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
3628 memset(&ddsd, 0, sizeof(ddsd));
3629 ddsd.dwSize = sizeof(ddsd);
3630 ddsd.dwFlags = DDSD_CAPS;
3631 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
3633 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
3634 ddsd.dwWidth = 64;
3635 ddsd.dwHeight = 64;
3637 if (tests[i].caps & DDSCAPS_ZBUFFER)
3639 ddsd.dwFlags |= DDSD_ZBUFFERBITDEPTH;
3640 U2(ddsd).dwZBufferBitDepth = z_depth;
3642 ddsd.ddsCaps.dwCaps = tests[i].caps;
3644 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3645 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
3647 memset(&ddsd, 0, sizeof(ddsd));
3648 ddsd.dwSize = sizeof(ddsd);
3649 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
3650 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
3651 if (SUCCEEDED(hr))
3653 hr = IDirectDrawSurface_Unlock(surface, NULL);
3654 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
3657 IDirectDrawSurface_Release(surface);
3660 refcount = IDirectDraw_Release(ddraw);
3661 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3662 DestroyWindow(window);
3665 static void test_surface_discard(void)
3667 IDirectDraw *ddraw;
3668 HRESULT hr;
3669 HWND window;
3670 DDSURFACEDESC ddsd;
3671 IDirectDrawSurface *surface, *primary;
3672 void *addr;
3673 static const struct
3675 DWORD caps;
3676 BOOL discard;
3678 tests[] =
3680 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, TRUE},
3681 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, FALSE},
3682 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, TRUE},
3683 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, FALSE},
3685 unsigned int i;
3687 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3688 0, 0, 640, 480, 0, 0, 0, 0);
3689 ddraw = create_ddraw();
3690 ok(!!ddraw, "Failed to create a ddraw object.\n");
3691 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3692 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3694 memset(&ddsd, 0, sizeof(ddsd));
3695 ddsd.dwSize = sizeof(ddsd);
3696 ddsd.dwFlags = DDSD_CAPS;
3697 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3698 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3700 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
3702 BOOL discarded;
3704 memset(&ddsd, 0, sizeof(ddsd));
3705 ddsd.dwSize = sizeof(ddsd);
3706 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3707 ddsd.ddsCaps.dwCaps = tests[i].caps;
3708 ddsd.dwWidth = 64;
3709 ddsd.dwHeight = 64;
3710 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3711 if (FAILED(hr))
3713 skip("Failed to create surface, skipping.\n");
3714 continue;
3717 memset(&ddsd, 0, sizeof(ddsd));
3718 ddsd.dwSize = sizeof(ddsd);
3719 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
3720 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
3721 addr = ddsd.lpSurface;
3722 hr = IDirectDrawSurface_Unlock(surface, NULL);
3723 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
3725 memset(&ddsd, 0, sizeof(ddsd));
3726 ddsd.dwSize = sizeof(ddsd);
3727 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
3728 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
3729 discarded = ddsd.lpSurface != addr;
3730 hr = IDirectDrawSurface_Unlock(surface, NULL);
3731 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
3733 hr = IDirectDrawSurface_Blt(primary, NULL, surface, NULL, DDBLT_WAIT, NULL);
3734 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
3736 memset(&ddsd, 0, sizeof(ddsd));
3737 ddsd.dwSize = sizeof(ddsd);
3738 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
3739 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
3740 discarded |= ddsd.lpSurface != addr;
3741 hr = IDirectDrawSurface_Unlock(surface, NULL);
3742 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
3744 IDirectDrawSurface_Release(surface);
3746 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
3747 * AMD r500, evergreen). Windows XP, at least on AMD r200, never changes the pointer. */
3748 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
3751 IDirectDrawSurface_Release(primary);
3752 IDirectDraw_Release(ddraw);
3753 DestroyWindow(window);
3756 static void test_flip(void)
3758 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
3759 IDirectDrawSurface *primary, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
3760 DDSCAPS caps = {DDSCAPS_FLIP};
3761 DDSURFACEDESC surface_desc;
3762 BOOL sysmem_primary;
3763 IDirectDraw *ddraw;
3764 D3DCOLOR color;
3765 ULONG refcount;
3766 HWND window;
3767 DDBLTFX fx;
3768 HRESULT hr;
3770 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3771 0, 0, 640, 480, 0, 0, 0, 0);
3772 ddraw = create_ddraw();
3773 ok(!!ddraw, "Failed to create a ddraw object.\n");
3775 hr = set_display_mode(ddraw, 640, 480);
3776 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3777 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3778 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3780 memset(&surface_desc, 0, sizeof(surface_desc));
3781 surface_desc.dwSize = sizeof(surface_desc);
3782 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
3783 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
3784 surface_desc.dwBackBufferCount = 3;
3785 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
3786 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3788 memset(&surface_desc, 0, sizeof(surface_desc));
3789 surface_desc.dwSize = sizeof(surface_desc);
3790 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
3791 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3792 ok((surface_desc.ddsCaps.dwCaps & ~placement)
3793 == (DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX),
3794 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3795 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
3797 hr = IDirectDrawSurface_GetAttachedSurface(primary, &caps, &backbuffer1);
3798 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3799 memset(&surface_desc, 0, sizeof(surface_desc));
3800 surface_desc.dwSize = sizeof(surface_desc);
3801 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer1, &surface_desc);
3802 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3803 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
3804 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_BACKBUFFER),
3805 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3807 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
3808 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3809 memset(&surface_desc, 0, sizeof(surface_desc));
3810 surface_desc.dwSize = sizeof(surface_desc);
3811 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer2, &surface_desc);
3812 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3813 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
3814 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
3815 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3817 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
3818 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3819 memset(&surface_desc, 0, sizeof(surface_desc));
3820 surface_desc.dwSize = sizeof(surface_desc);
3821 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer3, &surface_desc);
3822 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3823 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
3824 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
3825 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3827 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer3, &caps, &surface);
3828 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3829 ok(surface == primary, "Got unexpected surface %p, expected %p.\n", surface, primary);
3830 IDirectDrawSurface_Release(surface);
3832 memset(&surface_desc, 0, sizeof(surface_desc));
3833 surface_desc.dwSize = sizeof(surface_desc);
3834 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3835 surface_desc.ddsCaps.dwCaps = 0;
3836 surface_desc.dwWidth = 640;
3837 surface_desc.dwHeight = 480;
3838 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3839 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3840 hr = IDirectDrawSurface_Flip(primary, surface, DDFLIP_WAIT);
3841 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3842 IDirectDrawSurface_Release(surface);
3844 hr = IDirectDrawSurface_Flip(primary, primary, DDFLIP_WAIT);
3845 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3846 hr = IDirectDrawSurface_Flip(backbuffer1, NULL, DDFLIP_WAIT);
3847 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3848 hr = IDirectDrawSurface_Flip(backbuffer2, NULL, DDFLIP_WAIT);
3849 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3850 hr = IDirectDrawSurface_Flip(backbuffer3, NULL, DDFLIP_WAIT);
3851 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3853 memset(&fx, 0, sizeof(fx));
3854 fx.dwSize = sizeof(fx);
3855 U5(fx).dwFillColor = 0xffff0000;
3856 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3857 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3858 U5(fx).dwFillColor = 0xff00ff00;
3859 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3860 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3861 U5(fx).dwFillColor = 0xff0000ff;
3862 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3863 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3865 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
3866 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3867 color = get_surface_color(backbuffer1, 320, 240);
3868 /* The testbot seems to just copy the contents of one surface to all the
3869 * others, instead of properly flipping. */
3870 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
3871 "Got unexpected color 0x%08x.\n", color);
3872 color = get_surface_color(backbuffer2, 320, 240);
3873 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
3874 U5(fx).dwFillColor = 0xffff0000;
3875 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3876 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3878 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
3879 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3880 color = get_surface_color(backbuffer1, 320, 240);
3881 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
3882 "Got unexpected color 0x%08x.\n", color);
3883 color = get_surface_color(backbuffer2, 320, 240);
3884 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
3885 U5(fx).dwFillColor = 0xff00ff00;
3886 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3887 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3889 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
3890 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3891 color = get_surface_color(backbuffer1, 320, 240);
3892 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
3893 "Got unexpected color 0x%08x.\n", color);
3894 color = get_surface_color(backbuffer2, 320, 240);
3895 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3896 U5(fx).dwFillColor = 0xff0000ff;
3897 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3898 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3900 hr = IDirectDrawSurface_Flip(primary, backbuffer1, DDFLIP_WAIT);
3901 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3902 color = get_surface_color(backbuffer2, 320, 240);
3903 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
3904 "Got unexpected color 0x%08x.\n", color);
3905 color = get_surface_color(backbuffer3, 320, 240);
3906 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
3907 U5(fx).dwFillColor = 0xffff0000;
3908 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3909 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3911 hr = IDirectDrawSurface_Flip(primary, backbuffer2, DDFLIP_WAIT);
3912 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3913 color = get_surface_color(backbuffer1, 320, 240);
3914 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
3915 color = get_surface_color(backbuffer3, 320, 240);
3916 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
3917 "Got unexpected color 0x%08x.\n", color);
3918 U5(fx).dwFillColor = 0xff00ff00;
3919 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3920 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3922 hr = IDirectDrawSurface_Flip(primary, backbuffer3, DDFLIP_WAIT);
3923 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3924 color = get_surface_color(backbuffer1, 320, 240);
3925 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
3926 "Got unexpected color 0x%08x.\n", color);
3927 color = get_surface_color(backbuffer2, 320, 240);
3928 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3930 IDirectDrawSurface_Release(backbuffer3);
3931 IDirectDrawSurface_Release(backbuffer2);
3932 IDirectDrawSurface_Release(backbuffer1);
3933 IDirectDrawSurface_Release(primary);
3934 refcount = IDirectDraw_Release(ddraw);
3935 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3936 DestroyWindow(window);
3939 static void test_sysmem_overlay(void)
3941 IDirectDraw *ddraw;
3942 HWND window;
3943 HRESULT hr;
3944 DDSURFACEDESC ddsd;
3945 IDirectDrawSurface *surface;
3946 ULONG ref;
3948 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3949 0, 0, 640, 480, 0, 0, 0, 0);
3950 ddraw = create_ddraw();
3951 ok(!!ddraw, "Failed to create a ddraw object.\n");
3953 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3954 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3956 memset(&ddsd, 0, sizeof(ddsd));
3957 ddsd.dwSize = sizeof(ddsd);
3958 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
3959 ddsd.dwWidth = 16;
3960 ddsd.dwHeight = 16;
3961 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
3962 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
3963 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
3964 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
3965 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
3966 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
3967 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
3968 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3969 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
3971 ref = IDirectDraw_Release(ddraw);
3972 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
3973 DestroyWindow(window);
3976 static void test_primary_palette(void)
3978 DDSCAPS surface_caps = {DDSCAPS_FLIP};
3979 IDirectDrawSurface *primary, *backbuffer;
3980 PALETTEENTRY palette_entries[256];
3981 IDirectDrawPalette *palette, *tmp;
3982 DDSURFACEDESC surface_desc;
3983 IDirectDraw *ddraw;
3984 DWORD palette_caps;
3985 ULONG refcount;
3986 HWND window;
3987 HRESULT hr;
3989 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3990 0, 0, 640, 480, 0, 0, 0, 0);
3991 ddraw = create_ddraw();
3992 ok(!!ddraw, "Failed to create a ddraw object.\n");
3993 if (FAILED(hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 8)))
3995 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
3996 IDirectDraw_Release(ddraw);
3997 DestroyWindow(window);
3998 return;
4000 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4001 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4002 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4004 memset(&surface_desc, 0, sizeof(surface_desc));
4005 surface_desc.dwSize = sizeof(surface_desc);
4006 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4007 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4008 surface_desc.dwBackBufferCount = 1;
4009 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
4010 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4011 hr = IDirectDrawSurface_GetAttachedSurface(primary, &surface_caps, &backbuffer);
4012 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4014 memset(palette_entries, 0, sizeof(palette_entries));
4015 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
4016 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
4017 refcount = get_refcount((IUnknown *)palette);
4018 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4020 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
4021 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
4022 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
4024 hr = IDirectDrawSurface_SetPalette(primary, palette);
4025 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
4027 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
4028 * and is generally somewhat broken with respect to 8 bpp / palette
4029 * handling. */
4030 if (SUCCEEDED(IDirectDrawSurface_GetPalette(backbuffer, &tmp)))
4032 win_skip("Broken palette handling detected, skipping tests.\n");
4033 IDirectDrawPalette_Release(tmp);
4034 IDirectDrawPalette_Release(palette);
4035 /* The Windows 8 testbot keeps extra references to the primary and
4036 * backbuffer while in 8 bpp mode. */
4037 hr = IDirectDraw_RestoreDisplayMode(ddraw);
4038 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
4039 goto done;
4042 refcount = get_refcount((IUnknown *)palette);
4043 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4045 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
4046 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
4047 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
4048 "Got unexpected palette caps %#x.\n", palette_caps);
4050 hr = IDirectDrawSurface_SetPalette(primary, NULL);
4051 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
4052 refcount = get_refcount((IUnknown *)palette);
4053 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4055 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
4056 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
4057 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
4059 hr = IDirectDrawSurface_SetPalette(primary, palette);
4060 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
4061 refcount = get_refcount((IUnknown *)palette);
4062 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4064 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
4065 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
4066 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
4067 IDirectDrawPalette_Release(tmp);
4068 hr = IDirectDrawSurface_GetPalette(backbuffer, &tmp);
4069 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
4071 refcount = IDirectDrawPalette_Release(palette);
4072 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4073 refcount = IDirectDrawPalette_Release(palette);
4074 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4076 /* Note that this only seems to work when the palette is attached to the
4077 * primary surface. When attached to a regular surface, attempting to get
4078 * the palette here will cause an access violation. */
4079 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
4080 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
4082 done:
4083 refcount = IDirectDrawSurface_Release(backbuffer);
4084 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4085 refcount = IDirectDrawSurface_Release(primary);
4086 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4087 refcount = IDirectDraw_Release(ddraw);
4088 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4089 DestroyWindow(window);
4092 static HRESULT WINAPI surface_counter(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
4094 UINT *surface_count = context;
4096 ++(*surface_count);
4097 IDirectDrawSurface_Release(surface);
4099 return DDENUMRET_OK;
4102 static void test_surface_attachment(void)
4104 IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
4105 DDSCAPS caps = {DDSCAPS_TEXTURE};
4106 DDSURFACEDESC surface_desc;
4107 IDirectDraw *ddraw;
4108 UINT surface_count;
4109 ULONG refcount;
4110 HWND window;
4111 HRESULT hr;
4113 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4114 0, 0, 640, 480, 0, 0, 0, 0);
4115 ddraw = create_ddraw();
4116 ok(!!ddraw, "Failed to create a ddraw object.\n");
4117 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4118 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4120 memset(&surface_desc, 0, sizeof(surface_desc));
4121 surface_desc.dwSize = sizeof(surface_desc);
4122 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
4123 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
4124 U2(surface_desc).dwMipMapCount = 3;
4125 surface_desc.dwWidth = 128;
4126 surface_desc.dwHeight = 128;
4127 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4128 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4130 hr = IDirectDrawSurface_GetAttachedSurface(surface1, &caps, &surface2);
4131 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
4132 hr = IDirectDrawSurface_GetAttachedSurface(surface2, &caps, &surface3);
4133 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
4134 hr = IDirectDrawSurface_GetAttachedSurface(surface3, &caps, &surface4);
4135 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
4137 surface_count = 0;
4138 IDirectDrawSurface_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
4139 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
4140 surface_count = 0;
4141 IDirectDrawSurface_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
4142 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
4143 surface_count = 0;
4144 IDirectDrawSurface_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
4145 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
4147 memset(&surface_desc, 0, sizeof(surface_desc));
4148 surface_desc.dwSize = sizeof(surface_desc);
4149 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4150 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
4151 surface_desc.dwWidth = 16;
4152 surface_desc.dwHeight = 16;
4153 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4154 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4156 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
4157 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4158 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4159 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4160 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
4161 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4162 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
4163 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4164 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
4165 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4166 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
4167 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4169 IDirectDrawSurface_Release(surface4);
4171 memset(&surface_desc, 0, sizeof(surface_desc));
4172 surface_desc.dwSize = sizeof(surface_desc);
4173 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4174 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
4175 surface_desc.dwWidth = 16;
4176 surface_desc.dwHeight = 16;
4177 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4178 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4180 if (SUCCEEDED(hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4)))
4182 skip("Running on refrast, skipping some tests.\n");
4183 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface4);
4184 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4186 else
4188 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4189 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4190 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4191 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
4192 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4193 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
4194 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4195 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
4196 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4197 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
4198 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4201 IDirectDrawSurface_Release(surface4);
4202 IDirectDrawSurface_Release(surface3);
4203 IDirectDrawSurface_Release(surface2);
4204 IDirectDrawSurface_Release(surface1);
4206 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4207 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4209 /* Try a single primary and two offscreen plain surfaces. */
4210 memset(&surface_desc, 0, sizeof(surface_desc));
4211 surface_desc.dwSize = sizeof(surface_desc);
4212 surface_desc.dwFlags = DDSD_CAPS;
4213 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4214 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4215 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4217 memset(&surface_desc, 0, sizeof(surface_desc));
4218 surface_desc.dwSize = sizeof(surface_desc);
4219 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4220 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4221 surface_desc.dwWidth = GetSystemMetrics(SM_CXSCREEN);
4222 surface_desc.dwHeight = GetSystemMetrics(SM_CYSCREEN);
4223 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
4224 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4226 memset(&surface_desc, 0, sizeof(surface_desc));
4227 surface_desc.dwSize = sizeof(surface_desc);
4228 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4229 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4230 surface_desc.dwWidth = GetSystemMetrics(SM_CXSCREEN);
4231 surface_desc.dwHeight = GetSystemMetrics(SM_CYSCREEN);
4232 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
4233 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4235 /* This one has a different size. */
4236 memset(&surface_desc, 0, sizeof(surface_desc));
4237 surface_desc.dwSize = sizeof(surface_desc);
4238 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4239 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4240 surface_desc.dwWidth = 128;
4241 surface_desc.dwHeight = 128;
4242 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4243 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4245 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4246 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4247 /* Try the reverse without detaching first. */
4248 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
4249 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
4250 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4251 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4253 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
4254 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4255 /* Try to detach reversed. */
4256 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4257 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
4258 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
4259 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4261 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
4262 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4263 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
4264 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4266 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
4267 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4268 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4269 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4271 IDirectDrawSurface_Release(surface4);
4272 IDirectDrawSurface_Release(surface3);
4273 IDirectDrawSurface_Release(surface2);
4274 IDirectDrawSurface_Release(surface1);
4276 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
4277 memset(&surface_desc, 0, sizeof(surface_desc));
4278 surface_desc.dwSize = sizeof(surface_desc);
4279 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4280 surface_desc.dwWidth = 64;
4281 surface_desc.dwHeight = 64;
4282 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4283 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
4284 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
4285 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
4286 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
4287 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
4288 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
4289 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4290 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4291 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
4292 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4294 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4295 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
4296 U1(surface_desc.ddpfPixelFormat).dwZBufferBitDepth = 16;
4297 U3(surface_desc.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
4298 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
4299 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4301 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4302 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4303 refcount = get_refcount((IUnknown *)surface2);
4304 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4305 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4306 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
4308 /* Attaching while already attached to other surface. */
4309 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
4310 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4311 hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
4312 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4313 IDirectDrawSurface_Release(surface3);
4315 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4316 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4317 refcount = get_refcount((IUnknown *)surface2);
4318 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4320 /* Automatic detachment on release. */
4321 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4322 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4323 refcount = get_refcount((IUnknown *)surface2);
4324 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4325 refcount = IDirectDrawSurface_Release(surface1);
4326 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4327 refcount = IDirectDrawSurface_Release(surface2);
4328 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4329 refcount = IDirectDraw_Release(ddraw);
4330 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4331 DestroyWindow(window);
4334 static void test_pixel_format(void)
4336 HWND window, window2 = NULL;
4337 HDC hdc, hdc2 = NULL;
4338 HMODULE gl = NULL;
4339 int format, test_format;
4340 PIXELFORMATDESCRIPTOR pfd;
4341 IDirectDraw *ddraw = NULL;
4342 IDirectDrawClipper *clipper = NULL;
4343 DDSURFACEDESC ddsd;
4344 IDirectDrawSurface *primary = NULL;
4345 DDBLTFX fx;
4346 HRESULT hr;
4348 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4349 100, 100, 160, 160, NULL, NULL, NULL, NULL);
4350 if (!window)
4352 skip("Failed to create window\n");
4353 return;
4356 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4357 100, 100, 160, 160, NULL, NULL, NULL, NULL);
4359 hdc = GetDC(window);
4360 if (!hdc)
4362 skip("Failed to get DC\n");
4363 goto cleanup;
4366 if (window2)
4367 hdc2 = GetDC(window2);
4369 gl = LoadLibraryA("opengl32.dll");
4370 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
4372 format = GetPixelFormat(hdc);
4373 ok(format == 0, "new window has pixel format %d\n", format);
4375 ZeroMemory(&pfd, sizeof(pfd));
4376 pfd.nSize = sizeof(pfd);
4377 pfd.nVersion = 1;
4378 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
4379 pfd.iPixelType = PFD_TYPE_RGBA;
4380 pfd.iLayerType = PFD_MAIN_PLANE;
4381 format = ChoosePixelFormat(hdc, &pfd);
4382 if (format <= 0)
4384 skip("no pixel format available\n");
4385 goto cleanup;
4388 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
4390 skip("failed to set pixel format\n");
4391 goto cleanup;
4394 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
4396 skip("failed to set pixel format on second window\n");
4397 if (hdc2)
4399 ReleaseDC(window2, hdc2);
4400 hdc2 = NULL;
4404 ddraw = create_ddraw();
4405 ok(!!ddraw, "Failed to create a ddraw object.\n");
4407 test_format = GetPixelFormat(hdc);
4408 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4410 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4411 if (FAILED(hr))
4413 skip("Failed to set cooperative level, hr %#x.\n", hr);
4414 goto cleanup;
4417 test_format = GetPixelFormat(hdc);
4418 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4420 if (hdc2)
4422 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
4423 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
4424 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
4425 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
4427 test_format = GetPixelFormat(hdc);
4428 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4430 test_format = GetPixelFormat(hdc2);
4431 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4434 memset(&ddsd, 0, sizeof(ddsd));
4435 ddsd.dwSize = sizeof(ddsd);
4436 ddsd.dwFlags = DDSD_CAPS;
4437 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4439 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
4440 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4442 test_format = GetPixelFormat(hdc);
4443 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4445 if (hdc2)
4447 test_format = GetPixelFormat(hdc2);
4448 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4451 if (clipper)
4453 hr = IDirectDrawSurface_SetClipper(primary, clipper);
4454 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
4456 test_format = GetPixelFormat(hdc);
4457 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4459 test_format = GetPixelFormat(hdc2);
4460 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4463 memset(&fx, 0, sizeof(fx));
4464 fx.dwSize = sizeof(fx);
4465 hr = IDirectDrawSurface_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4466 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
4468 test_format = GetPixelFormat(hdc);
4469 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4471 if (hdc2)
4473 test_format = GetPixelFormat(hdc2);
4474 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4477 cleanup:
4478 if (primary) IDirectDrawSurface_Release(primary);
4479 if (clipper) IDirectDrawClipper_Release(clipper);
4480 if (ddraw) IDirectDraw_Release(ddraw);
4481 if (gl) FreeLibrary(gl);
4482 if (hdc) ReleaseDC(window, hdc);
4483 if (hdc2) ReleaseDC(window2, hdc2);
4484 if (window) DestroyWindow(window);
4485 if (window2) DestroyWindow(window2);
4488 static void test_create_surface_pitch(void)
4490 IDirectDrawSurface *surface;
4491 DDSURFACEDESC surface_desc;
4492 IDirectDraw *ddraw;
4493 unsigned int i;
4494 ULONG refcount;
4495 HWND window;
4496 HRESULT hr;
4497 void *mem;
4499 static const struct
4501 DWORD placement;
4502 DWORD flags_in;
4503 DWORD pitch_in;
4504 HRESULT hr;
4505 DWORD flags_out;
4506 DWORD pitch_out;
4508 test_data[] =
4510 {DDSCAPS_VIDEOMEMORY, 0, 0, DD_OK,
4511 DDSD_PITCH, 0x100},
4512 {DDSCAPS_VIDEOMEMORY, DDSD_PITCH, 0x104, DD_OK,
4513 DDSD_PITCH, 0x100},
4514 {DDSCAPS_VIDEOMEMORY, DDSD_PITCH, 0x0f8, DD_OK,
4515 DDSD_PITCH, 0x100},
4516 {DDSCAPS_VIDEOMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
4517 0, 0 },
4518 {DDSCAPS_SYSTEMMEMORY, 0, 0, DD_OK,
4519 DDSD_PITCH, 0x100},
4520 {DDSCAPS_SYSTEMMEMORY, DDSD_PITCH, 0x104, DD_OK,
4521 DDSD_PITCH, 0x100},
4522 {DDSCAPS_SYSTEMMEMORY, DDSD_PITCH, 0x0f8, DD_OK,
4523 DDSD_PITCH, 0x100},
4524 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
4525 0, 0 },
4526 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
4527 0, 0 },
4529 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE;
4531 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4532 0, 0, 640, 480, 0, 0, 0, 0);
4533 ddraw = create_ddraw();
4534 ok(!!ddraw, "Failed to create a ddraw object.\n");
4535 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4536 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4538 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
4540 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
4542 memset(&surface_desc, 0, sizeof(surface_desc));
4543 surface_desc.dwSize = sizeof(surface_desc);
4544 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
4545 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | test_data[i].placement;
4546 surface_desc.dwWidth = 63;
4547 surface_desc.dwHeight = 63;
4548 U1(surface_desc).lPitch = test_data[i].pitch_in;
4549 surface_desc.lpSurface = mem;
4550 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
4551 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
4552 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
4553 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4554 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4555 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4556 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4557 ok(hr == test_data[i].hr || (test_data[i].placement == DDSCAPS_VIDEOMEMORY && hr == DDERR_NODIRECTDRAWHW),
4558 "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
4559 if (FAILED(hr))
4560 continue;
4562 memset(&surface_desc, 0, sizeof(surface_desc));
4563 surface_desc.dwSize = sizeof(surface_desc);
4564 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4565 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
4566 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
4567 "Test %u: Got unexpected flags %#x, expected %#x.\n",
4568 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
4569 ok(U1(surface_desc).lPitch == test_data[i].pitch_out,
4570 "Test %u: Got unexpected pitch %u, expected %u.\n",
4571 i, U1(surface_desc).lPitch, test_data[i].pitch_out);
4573 IDirectDrawSurface_Release(surface);
4576 HeapFree(GetProcessHeap(), 0, mem);
4577 refcount = IDirectDraw_Release(ddraw);
4578 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4579 DestroyWindow(window);
4582 static void test_mipmap_lock(void)
4584 IDirectDrawSurface *surface, *surface2;
4585 DDSURFACEDESC surface_desc;
4586 IDirectDraw *ddraw;
4587 ULONG refcount;
4588 HWND window;
4589 HRESULT hr;
4590 DDSCAPS caps = {DDSCAPS_COMPLEX};
4591 DDCAPS hal_caps;
4593 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4594 0, 0, 640, 480, 0, 0, 0, 0);
4595 ddraw = create_ddraw();
4596 ok(!!ddraw, "Failed to create a ddraw object.\n");
4597 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4598 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4600 memset(&hal_caps, 0, sizeof(hal_caps));
4601 hal_caps.dwSize = sizeof(hal_caps);
4602 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
4603 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4604 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
4606 skip("Mipmapped textures not supported, skipping mipmap lock test.\n");
4607 IDirectDraw_Release(ddraw);
4608 DestroyWindow(window);
4609 return;
4612 memset(&surface_desc, 0, sizeof(surface_desc));
4613 surface_desc.dwSize = sizeof(surface_desc);
4614 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
4615 surface_desc.dwWidth = 4;
4616 surface_desc.dwHeight = 4;
4617 U2(surface_desc).dwMipMapCount = 2;
4618 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
4619 | DDSCAPS_SYSTEMMEMORY;
4620 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4621 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4622 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &surface2);
4623 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4625 memset(&surface_desc, 0, sizeof(surface_desc));
4626 surface_desc.dwSize = sizeof(surface_desc);
4627 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, 0, NULL);
4628 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4629 memset(&surface_desc, 0, sizeof(surface_desc));
4630 surface_desc.dwSize = sizeof(surface_desc);
4631 hr = IDirectDrawSurface_Lock(surface2, NULL, &surface_desc, 0, NULL);
4632 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4633 IDirectDrawSurface_Unlock(surface2, NULL);
4634 IDirectDrawSurface_Unlock(surface, NULL);
4636 IDirectDrawSurface_Release(surface2);
4637 IDirectDrawSurface_Release(surface);
4638 refcount = IDirectDraw_Release(ddraw);
4639 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4640 DestroyWindow(window);
4643 static void test_palette_complex(void)
4645 IDirectDrawSurface *surface, *mipmap, *tmp;
4646 DDSURFACEDESC surface_desc;
4647 IDirectDraw *ddraw;
4648 IDirectDrawPalette *palette, *palette2, *palette_mipmap;
4649 ULONG refcount;
4650 HWND window;
4651 HRESULT hr;
4652 DDSCAPS caps = {DDSCAPS_COMPLEX};
4653 DDCAPS hal_caps;
4654 PALETTEENTRY palette_entries[256];
4655 unsigned int i;
4656 HDC dc;
4657 RGBQUAD rgbquad;
4658 UINT count;
4660 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4661 0, 0, 640, 480, 0, 0, 0, 0);
4662 ddraw = create_ddraw();
4663 ok(!!ddraw, "Failed to create a ddraw object.\n");
4664 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4665 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4667 memset(&hal_caps, 0, sizeof(hal_caps));
4668 hal_caps.dwSize = sizeof(hal_caps);
4669 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
4670 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4671 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
4673 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
4674 IDirectDraw_Release(ddraw);
4675 DestroyWindow(window);
4676 return;
4679 memset(&surface_desc, 0, sizeof(surface_desc));
4680 surface_desc.dwSize = sizeof(surface_desc);
4681 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4682 surface_desc.dwWidth = 128;
4683 surface_desc.dwHeight = 128;
4684 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
4685 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
4686 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
4687 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
4688 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4689 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4691 memset(palette_entries, 0, sizeof(palette_entries));
4692 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
4693 palette_entries, &palette, NULL);
4694 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
4696 memset(palette_entries, 0, sizeof(palette_entries));
4697 palette_entries[1].peRed = 0xff;
4698 palette_entries[1].peGreen = 0x80;
4699 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
4700 palette_entries, &palette_mipmap, NULL);
4701 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
4703 palette2 = (void *)0xdeadbeef;
4704 hr = IDirectDrawSurface_GetPalette(surface, &palette2);
4705 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
4706 ok(!palette2, "Got unexpected palette %p.\n", palette2);
4707 hr = IDirectDrawSurface_SetPalette(surface, palette);
4708 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
4709 hr = IDirectDrawSurface_GetPalette(surface, &palette2);
4710 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
4711 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
4712 IDirectDrawPalette_Release(palette2);
4714 mipmap = surface;
4715 IDirectDrawSurface_AddRef(mipmap);
4716 for (i = 0; i < 7; ++i)
4718 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
4719 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
4720 palette2 = (void *)0xdeadbeef;
4721 hr = IDirectDrawSurface_GetPalette(tmp, &palette2);
4722 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
4723 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
4725 hr = IDirectDrawSurface_SetPalette(tmp, palette_mipmap);
4726 ok(SUCCEEDED(hr), "Failed to set palette, i %u, hr %#x.\n", i, hr);
4728 hr = IDirectDrawSurface_GetPalette(tmp, &palette2);
4729 ok(SUCCEEDED(hr), "Failed to get palette, i %u, hr %#x.\n", i, hr);
4730 ok(palette_mipmap == palette2, "Got unexpected palette %p.\n", palette2);
4731 IDirectDrawPalette_Release(palette2);
4733 hr = IDirectDrawSurface_GetDC(tmp, &dc);
4734 ok(SUCCEEDED(hr), "Failed to get DC, i %u, hr %#x.\n", i, hr);
4735 count = GetDIBColorTable(dc, 1, 1, &rgbquad);
4736 ok(count == 1, "Expected count 1, got %u.\n", count);
4737 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x.\n", rgbquad.rgbRed);
4738 ok(rgbquad.rgbGreen == 0x80, "Expected rgbGreen = 0x80, got %#x.\n", rgbquad.rgbGreen);
4739 ok(rgbquad.rgbBlue == 0x0, "Expected rgbBlue = 0x0, got %#x.\n", rgbquad.rgbBlue);
4740 hr = IDirectDrawSurface_ReleaseDC(tmp, dc);
4741 ok(SUCCEEDED(hr), "Failed to release DC, i %u, hr %#x.\n", i, hr);
4743 IDirectDrawSurface_Release(mipmap);
4744 mipmap = tmp;
4747 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
4748 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
4749 IDirectDrawSurface_Release(mipmap);
4750 refcount = IDirectDrawSurface_Release(surface);
4751 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4752 refcount = IDirectDrawPalette_Release(palette_mipmap);
4753 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4754 refcount = IDirectDrawPalette_Release(palette);
4755 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4757 refcount = IDirectDraw_Release(ddraw);
4758 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4759 DestroyWindow(window);
4762 static void test_p8_rgb_blit(void)
4764 IDirectDrawSurface *src, *dst;
4765 DDSURFACEDESC surface_desc;
4766 IDirectDraw *ddraw;
4767 IDirectDrawPalette *palette;
4768 ULONG refcount;
4769 HWND window;
4770 HRESULT hr;
4771 PALETTEENTRY palette_entries[256];
4772 unsigned int x;
4773 static const BYTE src_data[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
4774 static const D3DCOLOR expected[] =
4776 0x00000000, 0x00010101, 0x00020202, 0x00030303,
4777 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
4779 D3DCOLOR color;
4781 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4782 0, 0, 640, 480, 0, 0, 0, 0);
4783 ddraw = create_ddraw();
4784 ok(!!ddraw, "Failed to create a ddraw object.\n");
4785 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4786 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4788 memset(palette_entries, 0, sizeof(palette_entries));
4789 palette_entries[0].peRed = 0xff;
4790 palette_entries[1].peGreen = 0xff;
4791 palette_entries[2].peBlue = 0xff;
4792 palette_entries[3].peFlags = 0xff;
4793 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
4794 palette_entries, &palette, NULL);
4795 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
4797 memset(&surface_desc, 0, sizeof(surface_desc));
4798 surface_desc.dwSize = sizeof(surface_desc);
4799 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4800 surface_desc.dwWidth = 8;
4801 surface_desc.dwHeight = 1;
4802 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4803 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
4804 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
4805 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
4806 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src, NULL);
4807 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4809 memset(&surface_desc, 0, sizeof(surface_desc));
4810 surface_desc.dwSize = sizeof(surface_desc);
4811 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4812 surface_desc.dwWidth = 8;
4813 surface_desc.dwHeight = 1;
4814 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4815 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
4816 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
4817 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
4818 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4819 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4820 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4821 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
4822 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst, NULL);
4823 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4825 memset(&surface_desc, 0, sizeof(surface_desc));
4826 surface_desc.dwSize = sizeof(surface_desc);
4827 hr = IDirectDrawSurface_Lock(src, NULL, &surface_desc, 0, NULL);
4828 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
4829 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
4830 hr = IDirectDrawSurface_Unlock(src, NULL);
4831 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
4833 hr = IDirectDrawSurface_SetPalette(src, palette);
4834 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
4835 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
4836 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
4837 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
4838 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
4839 "Failed to blit, hr %#x.\n", hr);
4841 if (SUCCEEDED(hr))
4843 for (x = 0; x < sizeof(expected) / sizeof(*expected); x++)
4845 color = get_surface_color(dst, x, 0);
4846 todo_wine ok(compare_color(color, expected[x], 0),
4847 "Pixel %u: Got color %#x, expected %#x.\n",
4848 x, color, expected[x]);
4852 IDirectDrawSurface_Release(src);
4853 IDirectDrawSurface_Release(dst);
4854 IDirectDrawPalette_Release(palette);
4856 refcount = IDirectDraw_Release(ddraw);
4857 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4858 DestroyWindow(window);
4861 static void test_material(void)
4863 IDirect3DExecuteBuffer *execute_buffer;
4864 D3DMATERIALHANDLE mat_handle, tmp;
4865 D3DEXECUTEBUFFERDESC exec_desc;
4866 IDirect3DMaterial *material;
4867 IDirect3DViewport *viewport;
4868 IDirect3DDevice *device;
4869 IDirectDrawSurface *rt;
4870 IDirectDraw *ddraw;
4871 UINT inst_length;
4872 D3DCOLOR color;
4873 ULONG refcount;
4874 unsigned int i;
4875 HWND window;
4876 HRESULT hr;
4877 BOOL valid;
4878 void *ptr;
4880 static D3DVERTEX quad[] =
4882 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4883 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4884 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4885 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4887 static const struct
4889 BOOL material;
4890 D3DCOLOR expected_color;
4892 test_data[] =
4894 {TRUE, 0x0000ff00},
4895 {FALSE, 0x00ffffff},
4897 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4899 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4900 0, 0, 640, 480, 0, 0, 0, 0);
4901 ddraw = create_ddraw();
4902 ok(!!ddraw, "Failed to create a ddraw object.\n");
4903 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4905 skip("Failed to create a 3D device, skipping test.\n");
4906 DestroyWindow(window);
4907 return;
4910 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
4911 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4913 material = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
4914 viewport = create_viewport(device, 0, 0, 640, 480);
4915 viewport_set_background(device, viewport, material);
4917 destroy_material(material);
4918 material = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
4919 hr = IDirect3DMaterial_GetHandle(material, device, &mat_handle);
4920 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
4922 memset(&exec_desc, 0, sizeof(exec_desc));
4923 exec_desc.dwSize = sizeof(exec_desc);
4924 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
4925 exec_desc.dwBufferSize = 1024;
4926 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
4928 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
4929 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
4931 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
4933 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
4934 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
4936 memcpy(exec_desc.lpData, quad, sizeof(quad));
4937 ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad);
4938 emit_set_ls(&ptr, D3DLIGHTSTATE_MATERIAL, test_data[i].material ? mat_handle : 0);
4939 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
4940 emit_tquad(&ptr, 0);
4941 emit_end(&ptr);
4942 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
4943 inst_length -= sizeof(quad);
4945 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
4946 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
4948 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
4949 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4951 hr = IDirect3DDevice_BeginScene(device);
4952 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4953 set_execute_data(execute_buffer, 4, sizeof(quad), inst_length);
4954 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
4955 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
4956 hr = IDirect3DDevice_EndScene(device);
4957 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4958 color = get_surface_color(rt, 320, 240);
4959 if (test_data[i].material)
4960 todo_wine ok(compare_color(color, test_data[i].expected_color, 1)
4961 /* The Windows 8 testbot appears to return undefined results. */
4962 || broken(TRUE),
4963 "Got unexpected color 0x%08x, test %u.\n", color, i);
4964 else
4965 ok(compare_color(color, test_data[i].expected_color, 1),
4966 "Got unexpected color 0x%08x, test %u.\n", color, i);
4969 destroy_material(material);
4970 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
4971 hr = IDirect3DMaterial_GetHandle(material, device, &mat_handle);
4972 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
4974 hr = IDirect3DViewport_SetBackground(viewport, mat_handle);
4975 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
4976 hr = IDirect3DViewport_GetBackground(viewport, &tmp, &valid);
4977 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
4978 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
4979 ok(valid, "Got unexpected valid %#x.\n", valid);
4980 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
4981 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4982 color = get_surface_color(rt, 320, 240);
4983 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
4985 hr = IDirect3DViewport_SetBackground(viewport, 0);
4986 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
4987 hr = IDirect3DViewport_GetBackground(viewport, &tmp, &valid);
4988 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
4989 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
4990 ok(valid, "Got unexpected valid %#x.\n", valid);
4991 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
4992 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4993 color = get_surface_color(rt, 320, 240);
4994 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
4996 destroy_viewport(device, viewport);
4997 viewport = create_viewport(device, 0, 0, 640, 480);
4999 hr = IDirect3DViewport_GetBackground(viewport, &tmp, &valid);
5000 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
5001 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
5002 ok(!valid, "Got unexpected valid %#x.\n", valid);
5003 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
5004 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
5005 color = get_surface_color(rt, 320, 240);
5006 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x.\n", color);
5008 IDirect3DExecuteBuffer_Release(execute_buffer);
5009 destroy_viewport(device, viewport);
5010 destroy_material(material);
5011 IDirectDrawSurface_Release(rt);
5012 refcount = IDirect3DDevice_Release(device);
5013 ok(!refcount, "Device has %u references left.\n", refcount);
5014 refcount = IDirectDraw_Release(ddraw);
5015 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
5016 DestroyWindow(window);
5019 static void test_palette_gdi(void)
5021 IDirectDrawSurface *surface, *primary;
5022 DDSURFACEDESC surface_desc;
5023 IDirectDraw *ddraw;
5024 IDirectDrawPalette *palette, *palette2;
5025 ULONG refcount;
5026 HWND window;
5027 HRESULT hr;
5028 PALETTEENTRY palette_entries[256];
5029 UINT i;
5030 HDC dc;
5031 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
5032 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
5033 * not the point of this test. */
5034 static const RGBQUAD expected1[] =
5036 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
5037 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
5039 static const RGBQUAD expected2[] =
5041 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
5042 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
5044 static const RGBQUAD expected3[] =
5046 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
5047 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
5049 HPALETTE ddraw_palette_handle;
5050 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
5051 RGBQUAD rgbquad[255];
5052 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
5054 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5055 0, 0, 640, 480, 0, 0, 0, 0);
5056 ddraw = create_ddraw();
5057 ok(!!ddraw, "Failed to create a ddraw object.\n");
5058 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5059 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5061 memset(&surface_desc, 0, sizeof(surface_desc));
5062 surface_desc.dwSize = sizeof(surface_desc);
5063 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5064 surface_desc.dwWidth = 16;
5065 surface_desc.dwHeight = 16;
5066 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5067 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5068 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
5069 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
5070 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5071 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5073 /* Avoid colors from the Windows default palette. */
5074 memset(palette_entries, 0, sizeof(palette_entries));
5075 palette_entries[1].peRed = 0x01;
5076 palette_entries[2].peGreen = 0x02;
5077 palette_entries[3].peBlue = 0x03;
5078 palette_entries[4].peRed = 0x13;
5079 palette_entries[4].peGreen = 0x14;
5080 palette_entries[4].peBlue = 0x15;
5081 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
5082 palette_entries, &palette, NULL);
5083 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5085 /* If there is no palette assigned and the display mode is not 8 bpp, some
5086 * drivers refuse to create a DC while others allow it. If a DC is created,
5087 * the DIB color table is uninitialized and contains random colors. No error
5088 * is generated when trying to read pixels and random garbage is returned.
5090 * The most likely explanation is that if the driver creates a DC, it (or
5091 * the higher-level runtime) uses GetSystemPaletteEntries to find the
5092 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
5093 * contains uninitialized garbage. See comments below for the P8 case. */
5095 hr = IDirectDrawSurface_SetPalette(surface, palette);
5096 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5097 hr = IDirectDrawSurface_GetDC(surface, &dc);
5098 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
5099 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
5100 todo_wine ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
5101 "Got unexpected palette %p, expected %p.\n",
5102 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
5103 SelectPalette(dc, ddraw_palette_handle, FALSE);
5105 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
5106 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
5107 for (i = 0; i < sizeof(expected1) / sizeof(*expected1); i++)
5109 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
5110 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
5111 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
5112 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
5114 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
5116 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
5117 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
5118 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
5121 /* Update the palette while the DC is in use. This does not modify the DC. */
5122 palette_entries[4].peRed = 0x23;
5123 palette_entries[4].peGreen = 0x24;
5124 palette_entries[4].peBlue = 0x25;
5125 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
5126 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
5128 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
5129 ok(i == 1, "Expected count 1, got %u.\n", i);
5130 todo_wine ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
5131 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
5132 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
5133 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
5135 /* Neither does re-setting the palette. */
5136 hr = IDirectDrawSurface_SetPalette(surface, NULL);
5137 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5138 hr = IDirectDrawSurface_SetPalette(surface, palette);
5139 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5141 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
5142 ok(i == 1, "Expected count 1, got %u.\n", i);
5143 todo_wine ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
5144 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
5145 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
5146 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
5148 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
5149 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
5151 /* Refresh the DC. This updates the palette. */
5152 hr = IDirectDrawSurface_GetDC(surface, &dc);
5153 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
5154 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
5155 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
5156 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
5158 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
5159 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
5160 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
5161 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
5163 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
5165 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
5166 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
5167 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
5169 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
5170 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
5172 refcount = IDirectDrawSurface_Release(surface);
5173 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5175 if (FAILED(hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 8)))
5177 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
5178 IDirectDrawPalette_Release(palette);
5179 IDirectDraw_Release(ddraw);
5180 DestroyWindow(window);
5181 return;
5183 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
5184 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
5185 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5187 memset(&surface_desc, 0, sizeof(surface_desc));
5188 surface_desc.dwSize = sizeof(surface_desc);
5189 surface_desc.dwFlags = DDSD_CAPS;
5190 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
5191 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
5192 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5194 hr = IDirectDrawSurface_SetPalette(primary, palette);
5195 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5196 hr = IDirectDrawSurface_GetDC(primary, &dc);
5197 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
5198 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
5199 /* Windows 2000 on the testbot assigns a different palette to the primary. Refrast? */
5200 todo_wine ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE) || broken(TRUE),
5201 "Got unexpected palette %p, expected %p.\n",
5202 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
5203 SelectPalette(dc, ddraw_palette_handle, FALSE);
5205 /* The primary uses the system palette. In exclusive mode, the system palette matches
5206 * the ddraw palette attached to the primary, so the result is what you would expect
5207 * from a regular surface. Tests for the interaction between the ddraw palette and
5208 * the system palette are not included pending an application that depends on this.
5209 * The relation between those causes problems on Windows Vista and newer for games
5210 * like Age of Empires or Starcraft. Don't emulate it without a real need. */
5211 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
5212 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
5213 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
5215 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
5216 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
5217 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
5218 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
5220 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
5222 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
5223 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
5224 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
5226 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
5227 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
5229 memset(&surface_desc, 0, sizeof(surface_desc));
5230 surface_desc.dwSize = sizeof(surface_desc);
5231 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5232 surface_desc.dwWidth = 16;
5233 surface_desc.dwHeight = 16;
5234 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5235 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5236 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5238 /* Here the offscreen surface appears to use the primary's palette,
5239 * but in all likelyhood it is actually the system palette. */
5240 hr = IDirectDrawSurface_GetDC(surface, &dc);
5241 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
5242 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
5243 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
5244 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
5246 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
5247 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
5248 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
5249 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
5251 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
5253 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
5254 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
5255 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
5257 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
5258 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
5260 /* On real hardware a change to the primary surface's palette applies immediately,
5261 * even on device contexts from offscreen surfaces that do not have their own
5262 * palette. On the testbot VMs this is not the case. Don't test this until we
5263 * know of an application that depends on this. */
5265 memset(palette_entries, 0, sizeof(palette_entries));
5266 palette_entries[1].peBlue = 0x40;
5267 palette_entries[2].peRed = 0x40;
5268 palette_entries[3].peGreen = 0x40;
5269 palette_entries[4].peRed = 0x12;
5270 palette_entries[4].peGreen = 0x34;
5271 palette_entries[4].peBlue = 0x56;
5272 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
5273 palette_entries, &palette2, NULL);
5274 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5275 hr = IDirectDrawSurface_SetPalette(surface, palette2);
5276 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5278 /* A palette assigned to the offscreen surface overrides the primary / system
5279 * palette. */
5280 hr = IDirectDrawSurface_GetDC(surface, &dc);
5281 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
5282 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
5283 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
5284 for (i = 0; i < sizeof(expected3) / sizeof(*expected3); i++)
5286 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
5287 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
5288 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
5289 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
5291 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
5293 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
5294 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
5295 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
5297 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
5298 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
5300 refcount = IDirectDrawSurface_Release(surface);
5301 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5303 /* The Windows 8 testbot keeps extra references to the primary and
5304 * backbuffer while in 8 bpp mode. */
5305 hr = IDirectDraw_RestoreDisplayMode(ddraw);
5306 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
5308 refcount = IDirectDrawSurface_Release(primary);
5309 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5310 refcount = IDirectDrawPalette_Release(palette2);
5311 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5312 refcount = IDirectDrawPalette_Release(palette);
5313 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5314 refcount = IDirectDraw_Release(ddraw);
5315 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5316 DestroyWindow(window);
5319 START_TEST(ddraw1)
5321 IDirectDraw *ddraw;
5323 if (!(ddraw = create_ddraw()))
5325 skip("Failed to create a ddraw object, skipping tests.\n");
5326 return;
5328 IDirectDraw_Release(ddraw);
5330 test_coop_level_create_device_window();
5331 test_clipper_blt();
5332 test_coop_level_d3d_state();
5333 test_surface_interface_mismatch();
5334 test_coop_level_threaded();
5335 test_viewport();
5336 test_zenable();
5337 test_ck_rgba();
5338 test_ck_default();
5339 test_ck_complex();
5340 test_surface_qi();
5341 test_device_qi();
5342 test_wndproc();
5343 test_window_style();
5344 test_redundant_mode_set();
5345 test_coop_level_mode_set();
5346 test_coop_level_mode_set_multi();
5347 test_initialize();
5348 test_coop_level_surf_create();
5349 test_coop_level_multi_window();
5350 test_clear_rect_count();
5351 test_coop_level_activateapp();
5352 test_unsupported_formats();
5353 test_rt_caps();
5354 test_primary_caps();
5355 test_surface_lock();
5356 test_surface_discard();
5357 test_flip();
5358 test_sysmem_overlay();
5359 test_primary_palette();
5360 test_surface_attachment();
5361 test_pixel_format();
5362 test_create_surface_pitch();
5363 test_mipmap_lock();
5364 test_palette_complex();
5365 test_p8_rgb_blit();
5366 test_material();
5367 test_palette_gdi();