ddraw/tests: Skip A4R4G4B4 ckey tests on Nvidia.
[wine.git] / dlls / ddraw / tests / ddraw1.c
blob923aea33d4ea8e69a7209b66a445be74862a1be0
1 /*
2 * Copyright 2005 Antoine Chavasse (a.chavasse@gmail.com)
3 * Copyright 2008, 2011, 2012-2013 Stefan Dösinger for CodeWeavers
4 * Copyright 2011-2014 Henri Verbeet for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define COBJMACROS
22 #include "wine/test.h"
23 #include "d3d.h"
25 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
26 static DEVMODEW registry_mode;
28 struct create_window_thread_param
30 HWND window;
31 HANDLE window_created;
32 HANDLE destroy_window;
33 HANDLE thread;
36 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
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 c1 >>= 8; c2 >>= 8;
42 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
43 c1 >>= 8; c2 >>= 8;
44 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
45 return TRUE;
48 static IDirectDrawSurface *create_overlay(IDirectDraw *ddraw,
49 unsigned int width, unsigned int height, DWORD format)
51 IDirectDrawSurface *surface;
52 DDSURFACEDESC desc;
54 memset(&desc, 0, sizeof(desc));
55 desc.dwSize = sizeof(desc);
56 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
57 desc.dwWidth = width;
58 desc.dwHeight = height;
59 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
60 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
61 desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
62 desc.ddpfPixelFormat.dwFourCC = format;
64 if (FAILED(IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL)))
65 return NULL;
66 return surface;
69 static DWORD WINAPI create_window_thread_proc(void *param)
71 struct create_window_thread_param *p = param;
72 DWORD res;
73 BOOL ret;
75 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
76 0, 0, 640, 480, 0, 0, 0, 0);
77 ret = SetEvent(p->window_created);
78 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
80 for (;;)
82 MSG msg;
84 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
85 DispatchMessageA(&msg);
86 res = WaitForSingleObject(p->destroy_window, 100);
87 if (res == WAIT_OBJECT_0)
88 break;
89 if (res != WAIT_TIMEOUT)
91 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
92 break;
96 DestroyWindow(p->window);
98 return 0;
101 static void create_window_thread(struct create_window_thread_param *p)
103 DWORD res, tid;
105 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
106 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
107 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
108 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
109 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
110 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
111 res = WaitForSingleObject(p->window_created, INFINITE);
112 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
115 static void destroy_window_thread(struct create_window_thread_param *p)
117 SetEvent(p->destroy_window);
118 WaitForSingleObject(p->thread, INFINITE);
119 CloseHandle(p->destroy_window);
120 CloseHandle(p->window_created);
121 CloseHandle(p->thread);
124 static HRESULT set_display_mode(IDirectDraw *ddraw, DWORD width, DWORD height)
126 if (SUCCEEDED(IDirectDraw_SetDisplayMode(ddraw, width, height, 32)))
127 return DD_OK;
128 return IDirectDraw_SetDisplayMode(ddraw, width, height, 24);
131 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
133 RECT rect = {x, y, x + 1, y + 1};
134 DDSURFACEDESC surface_desc;
135 D3DCOLOR color;
136 HRESULT hr;
138 memset(&surface_desc, 0, sizeof(surface_desc));
139 surface_desc.dwSize = sizeof(surface_desc);
141 hr = IDirectDrawSurface_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
142 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
143 if (FAILED(hr))
144 return 0xdeadbeef;
146 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
148 hr = IDirectDrawSurface_Unlock(surface, NULL);
149 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
151 return color;
154 static void emit_process_vertices(void **ptr, DWORD flags, WORD base_idx, DWORD vertex_count)
156 D3DINSTRUCTION *inst = *ptr;
157 D3DPROCESSVERTICES *pv = (D3DPROCESSVERTICES *)(inst + 1);
159 inst->bOpcode = D3DOP_PROCESSVERTICES;
160 inst->bSize = sizeof(*pv);
161 inst->wCount = 1;
163 pv->dwFlags = flags;
164 pv->wStart = base_idx;
165 pv->wDest = 0;
166 pv->dwCount = vertex_count;
167 pv->dwReserved = 0;
169 *ptr = pv + 1;
172 static void emit_set_ts(void **ptr, D3DTRANSFORMSTATETYPE state, DWORD value)
174 D3DINSTRUCTION *inst = *ptr;
175 D3DSTATE *ts = (D3DSTATE *)(inst + 1);
177 inst->bOpcode = D3DOP_STATETRANSFORM;
178 inst->bSize = sizeof(*ts);
179 inst->wCount = 1;
181 U1(*ts).dtstTransformStateType = state;
182 U2(*ts).dwArg[0] = value;
184 *ptr = ts + 1;
187 static void emit_set_ls(void **ptr, D3DLIGHTSTATETYPE state, DWORD value)
189 D3DINSTRUCTION *inst = *ptr;
190 D3DSTATE *ls = (D3DSTATE *)(inst + 1);
192 inst->bOpcode = D3DOP_STATELIGHT;
193 inst->bSize = sizeof(*ls);
194 inst->wCount = 1;
196 U1(*ls).dlstLightStateType = state;
197 U2(*ls).dwArg[0] = value;
199 *ptr = ls + 1;
202 static void emit_set_rs(void **ptr, D3DRENDERSTATETYPE state, DWORD value)
204 D3DINSTRUCTION *inst = *ptr;
205 D3DSTATE *rs = (D3DSTATE *)(inst + 1);
207 inst->bOpcode = D3DOP_STATERENDER;
208 inst->bSize = sizeof(*rs);
209 inst->wCount = 1;
211 U1(*rs).drstRenderStateType = state;
212 U2(*rs).dwArg[0] = value;
214 *ptr = rs + 1;
217 static void emit_tquad(void **ptr, WORD base_idx)
219 D3DINSTRUCTION *inst = *ptr;
220 D3DTRIANGLE *tri = (D3DTRIANGLE *)(inst + 1);
222 inst->bOpcode = D3DOP_TRIANGLE;
223 inst->bSize = sizeof(*tri);
224 inst->wCount = 2;
226 U1(*tri).v1 = base_idx;
227 U2(*tri).v2 = base_idx + 1;
228 U3(*tri).v3 = base_idx + 2;
229 tri->wFlags = D3DTRIFLAG_START;
230 ++tri;
232 U1(*tri).v1 = base_idx + 2;
233 U2(*tri).v2 = base_idx + 1;
234 U3(*tri).v3 = base_idx + 3;
235 tri->wFlags = D3DTRIFLAG_ODD;
236 ++tri;
238 *ptr = tri;
241 static void emit_tquad_tlist(void **ptr, WORD base_idx)
243 D3DINSTRUCTION *inst = *ptr;
244 D3DTRIANGLE *tri = (D3DTRIANGLE *)(inst + 1);
246 inst->bOpcode = D3DOP_TRIANGLE;
247 inst->bSize = sizeof(*tri);
248 inst->wCount = 2;
250 U1(*tri).v1 = base_idx;
251 U2(*tri).v2 = base_idx + 1;
252 U3(*tri).v3 = base_idx + 2;
253 tri->wFlags = D3DTRIFLAG_START;
254 ++tri;
256 U1(*tri).v1 = base_idx + 2;
257 U2(*tri).v2 = base_idx + 3;
258 U3(*tri).v3 = base_idx;
259 tri->wFlags = D3DTRIFLAG_START;
260 ++tri;
262 *ptr = tri;
265 static void emit_end(void **ptr)
267 D3DINSTRUCTION *inst = *ptr;
269 inst->bOpcode = D3DOP_EXIT;
270 inst->bSize = 0;
271 inst->wCount = 0;
273 *ptr = inst + 1;
276 static void set_execute_data(IDirect3DExecuteBuffer *execute_buffer, UINT vertex_count, UINT offset, UINT len)
278 D3DEXECUTEDATA exec_data;
279 HRESULT hr;
281 memset(&exec_data, 0, sizeof(exec_data));
282 exec_data.dwSize = sizeof(exec_data);
283 exec_data.dwVertexCount = vertex_count;
284 exec_data.dwInstructionOffset = offset;
285 exec_data.dwInstructionLength = len;
286 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
287 ok(SUCCEEDED(hr), "Failed to set execute data, hr %#x.\n", hr);
290 static DWORD get_device_z_depth(IDirect3DDevice *device)
292 DDSCAPS caps = {DDSCAPS_ZBUFFER};
293 IDirectDrawSurface *ds, *rt;
294 DDSURFACEDESC desc;
295 HRESULT hr;
297 if (FAILED(IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt)))
298 return 0;
300 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ds);
301 IDirectDrawSurface_Release(rt);
302 if (FAILED(hr))
303 return 0;
305 desc.dwSize = sizeof(desc);
306 hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
307 IDirectDrawSurface_Release(ds);
308 if (FAILED(hr))
309 return 0;
311 return U2(desc).dwZBufferBitDepth;
314 static IDirectDraw *create_ddraw(void)
316 IDirectDraw *ddraw;
318 if (FAILED(DirectDrawCreate(NULL, &ddraw, NULL)))
319 return NULL;
321 return ddraw;
324 static IDirect3DDevice *create_device(IDirectDraw *ddraw, HWND window, DWORD coop_level)
326 static const DWORD z_depths[] = {32, 24, 16};
327 IDirectDrawSurface *surface, *ds;
328 IDirect3DDevice *device = NULL;
329 DDSURFACEDESC surface_desc;
330 unsigned int i;
331 HRESULT hr;
333 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, coop_level);
334 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
336 memset(&surface_desc, 0, sizeof(surface_desc));
337 surface_desc.dwSize = sizeof(surface_desc);
338 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
339 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
340 surface_desc.dwWidth = 640;
341 surface_desc.dwHeight = 480;
343 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
344 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
346 if (coop_level & DDSCL_NORMAL)
348 IDirectDrawClipper *clipper;
350 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
351 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
352 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
353 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
354 hr = IDirectDrawSurface_SetClipper(surface, clipper);
355 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
356 IDirectDrawClipper_Release(clipper);
359 /* We used to use EnumDevices() for this, but it seems
360 * D3DDEVICEDESC.dwDeviceZBufferBitDepth only has a very casual
361 * relationship with reality. */
362 for (i = 0; i < sizeof(z_depths) / sizeof(*z_depths); ++i)
364 memset(&surface_desc, 0, sizeof(surface_desc));
365 surface_desc.dwSize = sizeof(surface_desc);
366 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
367 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
368 U2(surface_desc).dwZBufferBitDepth = z_depths[i];
369 surface_desc.dwWidth = 640;
370 surface_desc.dwHeight = 480;
371 if (FAILED(IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL)))
372 continue;
374 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
375 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
376 IDirectDrawSurface_Release(ds);
377 if (FAILED(hr))
378 continue;
380 if (SUCCEEDED(IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device)))
381 break;
383 IDirectDrawSurface_DeleteAttachedSurface(surface, 0, ds);
386 IDirectDrawSurface_Release(surface);
387 return device;
390 static IDirect3DViewport *create_viewport(IDirect3DDevice *device, UINT x, UINT y, UINT w, UINT h)
392 IDirect3DViewport *viewport;
393 D3DVIEWPORT vp;
394 IDirect3D *d3d;
395 HRESULT hr;
397 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
398 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
399 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
400 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
401 hr = IDirect3DDevice_AddViewport(device, viewport);
402 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
403 memset(&vp, 0, sizeof(vp));
404 vp.dwSize = sizeof(vp);
405 vp.dwX = x;
406 vp.dwY = y;
407 vp.dwWidth = w;
408 vp.dwHeight = h;
409 vp.dvScaleX = (float)w / 2.0f;
410 vp.dvScaleY = (float)h / 2.0f;
411 vp.dvMaxX = 1.0f;
412 vp.dvMaxY = 1.0f;
413 vp.dvMinZ = 0.0f;
414 vp.dvMaxZ = 1.0f;
415 hr = IDirect3DViewport_SetViewport(viewport, &vp);
416 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
417 IDirect3D_Release(d3d);
419 return viewport;
422 static void viewport_set_background(IDirect3DDevice *device, IDirect3DViewport *viewport,
423 IDirect3DMaterial *material)
425 D3DMATERIALHANDLE material_handle;
426 HRESULT hr;
428 hr = IDirect3DMaterial2_GetHandle(material, device, &material_handle);
429 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
430 hr = IDirect3DViewport2_SetBackground(viewport, material_handle);
431 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
434 static void destroy_viewport(IDirect3DDevice *device, IDirect3DViewport *viewport)
436 HRESULT hr;
438 hr = IDirect3DDevice_DeleteViewport(device, viewport);
439 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
440 IDirect3DViewport_Release(viewport);
443 static IDirect3DMaterial *create_material(IDirect3DDevice *device, D3DMATERIAL *mat)
445 IDirect3DMaterial *material;
446 IDirect3D *d3d;
447 HRESULT hr;
449 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
450 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
451 hr = IDirect3D_CreateMaterial(d3d, &material, NULL);
452 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
453 hr = IDirect3DMaterial_SetMaterial(material, mat);
454 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
455 IDirect3D_Release(d3d);
457 return material;
460 static IDirect3DMaterial *create_diffuse_material(IDirect3DDevice *device, float r, float g, float b, float a)
462 D3DMATERIAL mat;
464 memset(&mat, 0, sizeof(mat));
465 mat.dwSize = sizeof(mat);
466 U1(U(mat).diffuse).r = r;
467 U2(U(mat).diffuse).g = g;
468 U3(U(mat).diffuse).b = b;
469 U4(U(mat).diffuse).a = a;
471 return create_material(device, &mat);
474 static IDirect3DMaterial *create_emissive_material(IDirect3DDevice *device, float r, float g, float b, float a)
476 D3DMATERIAL mat;
478 memset(&mat, 0, sizeof(mat));
479 mat.dwSize = sizeof(mat);
480 U1(U3(mat).emissive).r = r;
481 U2(U3(mat).emissive).g = g;
482 U3(U3(mat).emissive).b = b;
483 U4(U3(mat).emissive).a = a;
485 return create_material(device, &mat);
488 static void destroy_material(IDirect3DMaterial *material)
490 IDirect3DMaterial_Release(material);
493 struct message
495 UINT message;
496 BOOL check_wparam;
497 WPARAM expect_wparam;
500 static const struct message *expect_messages;
502 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
504 if (expect_messages && message == expect_messages->message)
506 if (expect_messages->check_wparam)
507 ok (wparam == expect_messages->expect_wparam,
508 "Got unexpected wparam %lx for message %x, expected %lx.\n",
509 wparam, message, expect_messages->expect_wparam);
511 ++expect_messages;
514 return DefWindowProcA(hwnd, message, wparam, lparam);
517 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
518 * interface. This prevents subsequent SetCooperativeLevel() calls on a
519 * different window from failing with DDERR_HWNDALREADYSET. */
520 static void fix_wndproc(HWND window, LONG_PTR proc)
522 IDirectDraw *ddraw;
523 HRESULT hr;
525 if (!(ddraw = create_ddraw()))
526 return;
528 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
529 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
530 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
531 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
532 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
534 IDirectDraw_Release(ddraw);
537 static HRESULT CALLBACK restore_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
539 HRESULT hr = IDirectDrawSurface_Restore(surface);
540 ok(SUCCEEDED(hr) || hr == DDERR_IMPLICITLYCREATED, "Failed to restore surface, hr %#x.\n", hr);
541 IDirectDrawSurface_Release(surface);
543 return DDENUMRET_OK;
546 static HRESULT restore_surfaces(IDirectDraw *ddraw)
548 return IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
549 NULL, NULL, restore_callback);
552 static void test_coop_level_create_device_window(void)
554 HWND focus_window, device_window;
555 IDirectDraw *ddraw;
556 HRESULT hr;
558 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
559 0, 0, 640, 480, 0, 0, 0, 0);
560 ddraw = create_ddraw();
561 ok(!!ddraw, "Failed to create a ddraw object.\n");
563 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
564 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
565 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
566 ok(!device_window, "Unexpected device window found.\n");
567 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
568 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
569 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
570 ok(!device_window, "Unexpected device window found.\n");
571 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
572 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
573 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
574 ok(!device_window, "Unexpected device window found.\n");
575 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
576 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
577 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
578 ok(!device_window, "Unexpected device window found.\n");
579 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
580 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
581 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
582 ok(!device_window, "Unexpected device window found.\n");
584 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
585 if (broken(hr == DDERR_INVALIDPARAMS))
587 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
588 IDirectDraw_Release(ddraw);
589 DestroyWindow(focus_window);
590 return;
593 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
594 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
595 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
596 ok(!device_window, "Unexpected device window found.\n");
597 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
598 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
599 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
600 ok(!device_window, "Unexpected device window found.\n");
602 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
603 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
604 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
605 ok(!device_window, "Unexpected device window found.\n");
606 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
607 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
608 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
609 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
610 ok(!!device_window, "Device window not found.\n");
612 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
613 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
614 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
615 ok(!device_window, "Unexpected device window found.\n");
616 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
617 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
618 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
619 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
620 ok(!!device_window, "Device window not found.\n");
622 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
623 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
624 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
625 ok(!device_window, "Unexpected device window found.\n");
626 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
627 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
628 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
629 ok(!device_window, "Unexpected device window found.\n");
630 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
631 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
632 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
633 ok(!device_window, "Unexpected device window found.\n");
634 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
635 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
636 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
637 ok(!!device_window, "Device window not found.\n");
639 IDirectDraw_Release(ddraw);
640 DestroyWindow(focus_window);
643 static void test_clipper_blt(void)
645 IDirectDrawSurface *src_surface, *dst_surface;
646 RECT client_rect, src_rect;
647 IDirectDrawClipper *clipper;
648 DDSURFACEDESC surface_desc;
649 unsigned int i, j, x, y;
650 IDirectDraw *ddraw;
651 RGNDATA *rgn_data;
652 D3DCOLOR color;
653 ULONG refcount;
654 HRGN r1, r2;
655 HWND window;
656 DDBLTFX fx;
657 HRESULT hr;
658 DWORD *ptr;
659 DWORD ret;
661 static const DWORD src_data[] =
663 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
664 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
665 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
667 static const D3DCOLOR expected1[] =
669 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
670 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
671 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
672 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
674 /* Nvidia on Windows seems to have an off-by-one error
675 * when processing source rectangles. Our left = 1 and
676 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
677 * read as well, but only for the edge pixels on the
678 * output image. The bug happens on the y axis as well,
679 * but we only read one row there, and all source rows
680 * contain the same data. This bug is not dependent on
681 * the presence of a clipper. */
682 static const D3DCOLOR expected1_broken[] =
684 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
685 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
686 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
687 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
689 static const D3DCOLOR expected2[] =
691 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
692 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
693 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
694 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
697 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
698 10, 10, 640, 480, 0, 0, 0, 0);
699 ShowWindow(window, SW_SHOW);
700 ddraw = create_ddraw();
701 ok(!!ddraw, "Failed to create a ddraw object.\n");
703 ret = GetClientRect(window, &client_rect);
704 ok(ret, "Failed to get client rect.\n");
705 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
706 ok(ret, "Failed to map client rect.\n");
708 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
709 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
711 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
712 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
713 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
714 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
715 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
716 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
717 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
718 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
719 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
720 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
721 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
722 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
723 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
724 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
725 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
726 "Got unexpected bounding rect %s, expected %s.\n",
727 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
728 HeapFree(GetProcessHeap(), 0, rgn_data);
730 r1 = CreateRectRgn(0, 0, 320, 240);
731 ok(!!r1, "Failed to create region.\n");
732 r2 = CreateRectRgn(320, 240, 640, 480);
733 ok(!!r2, "Failed to create region.\n");
734 CombineRgn(r1, r1, r2, RGN_OR);
735 ret = GetRegionData(r1, 0, NULL);
736 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
737 ret = GetRegionData(r1, ret, rgn_data);
738 ok(!!ret, "Failed to get region data.\n");
740 DeleteObject(r2);
741 DeleteObject(r1);
743 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
744 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
745 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
746 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
747 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
748 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
750 HeapFree(GetProcessHeap(), 0, rgn_data);
752 memset(&surface_desc, 0, sizeof(surface_desc));
753 surface_desc.dwSize = sizeof(surface_desc);
754 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
755 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
756 surface_desc.dwWidth = 640;
757 surface_desc.dwHeight = 480;
758 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
759 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
760 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
761 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
762 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
763 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
765 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
766 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
767 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
768 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
770 memset(&fx, 0, sizeof(fx));
771 fx.dwSize = sizeof(fx);
772 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
773 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
774 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
775 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
777 hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
778 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
779 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
780 ptr = surface_desc.lpSurface;
781 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
782 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
783 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
784 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
785 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
787 hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
788 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
790 SetRect(&src_rect, 1, 1, 5, 2);
791 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
792 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
793 for (i = 0; i < 4; ++i)
795 for (j = 0; j < 4; ++j)
797 x = 80 * ((2 * j) + 1);
798 y = 60 * ((2 * i) + 1);
799 color = get_surface_color(dst_surface, x, y);
800 ok(compare_color(color, expected1[i * 4 + j], 1)
801 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
802 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
806 U5(fx).dwFillColor = 0xff0000ff;
807 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
808 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
809 for (i = 0; i < 4; ++i)
811 for (j = 0; j < 4; ++j)
813 x = 80 * ((2 * j) + 1);
814 y = 60 * ((2 * i) + 1);
815 color = get_surface_color(dst_surface, x, y);
816 ok(compare_color(color, expected2[i * 4 + j], 1),
817 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
821 hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
822 ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
824 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
825 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
826 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
827 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
828 DestroyWindow(window);
829 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
830 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
831 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
832 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
833 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
834 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
835 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
836 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
837 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
838 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
839 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
840 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
842 IDirectDrawSurface_Release(dst_surface);
843 IDirectDrawSurface_Release(src_surface);
844 refcount = IDirectDrawClipper_Release(clipper);
845 ok(!refcount, "Clipper has %u references left.\n", refcount);
846 IDirectDraw_Release(ddraw);
849 static void test_coop_level_d3d_state(void)
851 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
852 IDirectDrawSurface *rt, *surface;
853 IDirect3DMaterial *background;
854 IDirect3DViewport *viewport;
855 IDirect3DDevice *device;
856 D3DMATERIAL material;
857 IDirectDraw *ddraw;
858 D3DCOLOR color;
859 HWND window;
860 HRESULT hr;
862 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
863 0, 0, 640, 480, 0, 0, 0, 0);
864 ddraw = create_ddraw();
865 ok(!!ddraw, "Failed to create a ddraw object.\n");
866 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
868 skip("Failed to create a 3D device, skipping test.\n");
869 IDirectDraw_Release(ddraw);
870 DestroyWindow(window);
871 return;
874 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
875 viewport = create_viewport(device, 0, 0, 640, 480);
876 viewport_set_background(device, viewport, background);
878 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
879 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
880 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
881 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
882 color = get_surface_color(rt, 320, 240);
883 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
885 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
886 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
887 hr = IDirectDrawSurface_IsLost(rt);
888 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
889 hr = restore_surfaces(ddraw);
890 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
892 memset(&material, 0, sizeof(material));
893 material.dwSize = sizeof(material);
894 U1(U(material).diffuse).r = 0.0f;
895 U2(U(material).diffuse).g = 1.0f;
896 U3(U(material).diffuse).b = 0.0f;
897 U4(U(material).diffuse).a = 1.0f;
898 hr = IDirect3DMaterial_SetMaterial(background, &material);
899 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
901 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&surface);
902 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
903 ok(surface == rt, "Got unexpected surface %p.\n", surface);
904 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
905 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
906 color = get_surface_color(rt, 320, 240);
907 ok(compare_color(color, 0x0000ff00, 1) || broken(compare_color(color, 0x00000000, 1)),
908 "Got unexpected color 0x%08x.\n", color);
910 destroy_viewport(device, viewport);
911 destroy_material(background);
912 IDirectDrawSurface_Release(surface);
913 IDirectDrawSurface_Release(rt);
914 IDirect3DDevice_Release(device);
915 IDirectDraw_Release(ddraw);
916 DestroyWindow(window);
919 static void test_surface_interface_mismatch(void)
921 IDirectDraw *ddraw = NULL;
922 IDirectDrawSurface *surface = NULL, *ds;
923 IDirectDrawSurface3 *surface3 = NULL;
924 IDirect3DDevice *device = NULL;
925 IDirect3DViewport *viewport = NULL;
926 IDirect3DMaterial *background = NULL;
927 DDSURFACEDESC surface_desc;
928 DWORD z_depth = 0;
929 ULONG refcount;
930 HRESULT hr;
931 D3DCOLOR color;
932 HWND window;
933 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
935 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
936 0, 0, 640, 480, 0, 0, 0, 0);
937 ddraw = create_ddraw();
938 ok(!!ddraw, "Failed to create a ddraw object.\n");
939 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
941 skip("Failed to create a 3D device, skipping test.\n");
942 IDirectDraw_Release(ddraw);
943 DestroyWindow(window);
944 return;
946 z_depth = get_device_z_depth(device);
947 ok(!!z_depth, "Failed to get device z depth.\n");
948 IDirect3DDevice_Release(device);
949 device = NULL;
951 memset(&surface_desc, 0, sizeof(surface_desc));
952 surface_desc.dwSize = sizeof(surface_desc);
953 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
954 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
955 surface_desc.dwWidth = 640;
956 surface_desc.dwHeight = 480;
958 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
959 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
961 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
962 if (FAILED(hr))
964 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
965 goto cleanup;
968 memset(&surface_desc, 0, sizeof(surface_desc));
969 surface_desc.dwSize = sizeof(surface_desc);
970 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
971 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
972 U2(surface_desc).dwZBufferBitDepth = z_depth;
973 surface_desc.dwWidth = 640;
974 surface_desc.dwHeight = 480;
975 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL);
976 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
977 if (FAILED(hr))
978 goto cleanup;
980 /* Using a different surface interface version still works */
981 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
982 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
983 refcount = IDirectDrawSurface_Release(ds);
984 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
985 if (FAILED(hr))
986 goto cleanup;
988 /* Here too */
989 hr = IDirectDrawSurface3_QueryInterface(surface3, &IID_IDirect3DHALDevice, (void **)&device);
990 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
991 if (FAILED(hr))
992 goto cleanup;
994 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
995 viewport = create_viewport(device, 0, 0, 640, 480);
996 viewport_set_background(device, viewport, background);
998 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
999 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1000 color = get_surface_color(surface, 320, 240);
1001 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1003 cleanup:
1004 if (viewport)
1005 destroy_viewport(device, viewport);
1006 if (background)
1007 destroy_material(background);
1008 if (surface3) IDirectDrawSurface3_Release(surface3);
1009 if (surface) IDirectDrawSurface_Release(surface);
1010 if (device) IDirect3DDevice_Release(device);
1011 if (ddraw) IDirectDraw_Release(ddraw);
1012 DestroyWindow(window);
1015 static void test_coop_level_threaded(void)
1017 struct create_window_thread_param p;
1018 IDirectDraw *ddraw;
1019 HRESULT hr;
1021 ddraw = create_ddraw();
1022 ok(!!ddraw, "Failed to create a ddraw object.\n");
1023 create_window_thread(&p);
1025 hr = IDirectDraw_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1026 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1028 IDirectDraw_Release(ddraw);
1029 destroy_window_thread(&p);
1032 static ULONG get_refcount(IUnknown *test_iface)
1034 IUnknown_AddRef(test_iface);
1035 return IUnknown_Release(test_iface);
1038 static void test_viewport(void)
1040 IDirectDraw *ddraw;
1041 IDirect3D *d3d;
1042 HRESULT hr;
1043 ULONG ref;
1044 IDirect3DViewport *viewport, *another_vp;
1045 IDirect3DViewport2 *viewport2;
1046 IDirect3DViewport3 *viewport3;
1047 IDirectDrawGammaControl *gamma;
1048 IUnknown *unknown;
1049 IDirect3DDevice *device;
1050 HWND window;
1052 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1053 0, 0, 640, 480, 0, 0, 0, 0);
1054 ddraw = create_ddraw();
1055 ok(!!ddraw, "Failed to create a ddraw object.\n");
1056 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1058 skip("Failed to create a 3D device, skipping test.\n");
1059 IDirectDraw_Release(ddraw);
1060 DestroyWindow(window);
1061 return;
1064 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
1065 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1066 ref = get_refcount((IUnknown *) d3d);
1067 ok(ref == 2, "IDirect3D refcount is %d\n", ref);
1069 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
1070 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1071 ref = get_refcount((IUnknown *)viewport);
1072 ok(ref == 1, "Initial IDirect3DViewport refcount is %u\n", ref);
1073 ref = get_refcount((IUnknown *)d3d);
1074 ok(ref == 2, "IDirect3D refcount is %u\n", ref);
1076 /* E_FAIL return values are returned by Winetestbot Windows NT machines. While not supporting
1077 * newer interfaces is legitimate for old ddraw versions, E_FAIL violates Microsoft's rules
1078 * for QueryInterface, hence the broken() */
1079 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1080 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirectDrawGammaControl, (void **)&gamma);
1081 ok(hr == E_NOINTERFACE || broken(hr == E_FAIL), "Got unexpected hr %#x.\n", hr);
1082 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1083 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1084 /* NULL iid: Segfaults */
1086 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport2, (void **)&viewport2);
1087 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
1088 "Failed to QI IDirect3DViewport2, hr %#x.\n", hr);
1089 if (viewport2)
1091 ref = get_refcount((IUnknown *)viewport);
1092 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1093 ref = get_refcount((IUnknown *)viewport2);
1094 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1095 IDirect3DViewport2_Release(viewport2);
1096 viewport2 = NULL;
1099 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport3, (void **)&viewport3);
1100 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
1101 "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1102 if (viewport3)
1104 ref = get_refcount((IUnknown *)viewport);
1105 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1106 ref = get_refcount((IUnknown *)viewport3);
1107 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1108 IDirect3DViewport3_Release(viewport3);
1111 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IUnknown, (void **)&unknown);
1112 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1113 if (unknown)
1115 ref = get_refcount((IUnknown *)viewport);
1116 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1117 ref = get_refcount(unknown);
1118 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1119 IUnknown_Release(unknown);
1122 /* AddViewport(NULL): Segfault */
1123 hr = IDirect3DDevice_DeleteViewport(device, NULL);
1124 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1126 hr = IDirect3D_CreateViewport(d3d, &another_vp, NULL);
1127 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1129 hr = IDirect3DDevice_AddViewport(device, viewport);
1130 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1131 ref = get_refcount((IUnknown *) viewport);
1132 ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
1133 hr = IDirect3DDevice_AddViewport(device, another_vp);
1134 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1135 ref = get_refcount((IUnknown *) another_vp);
1136 ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
1138 hr = IDirect3DDevice_DeleteViewport(device, another_vp);
1139 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1140 ref = get_refcount((IUnknown *) another_vp);
1141 ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
1143 IDirect3DDevice_Release(device);
1144 ref = get_refcount((IUnknown *) viewport);
1145 ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
1147 IDirect3DViewport_Release(another_vp);
1148 IDirect3D_Release(d3d);
1149 IDirect3DViewport_Release(viewport);
1150 DestroyWindow(window);
1151 IDirectDraw_Release(ddraw);
1154 static void test_zenable(void)
1156 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1157 static D3DTLVERTEX tquad[] =
1159 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1160 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1161 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1162 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1164 IDirect3DExecuteBuffer *execute_buffer;
1165 D3DEXECUTEBUFFERDESC exec_desc;
1166 IDirect3DMaterial *background;
1167 IDirect3DViewport *viewport;
1168 IDirect3DDevice *device;
1169 IDirectDrawSurface *rt;
1170 IDirectDraw *ddraw;
1171 UINT inst_length;
1172 D3DCOLOR color;
1173 HWND window;
1174 HRESULT hr;
1175 UINT x, y;
1176 UINT i, j;
1177 void *ptr;
1179 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1180 0, 0, 640, 480, 0, 0, 0, 0);
1181 ddraw = create_ddraw();
1182 ok(!!ddraw, "Failed to create a ddraw object.\n");
1183 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1185 skip("Failed to create a 3D device, skipping test.\n");
1186 IDirectDraw_Release(ddraw);
1187 DestroyWindow(window);
1188 return;
1191 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1192 viewport = create_viewport(device, 0, 0, 640, 480);
1193 viewport_set_background(device, viewport, background);
1195 memset(&exec_desc, 0, sizeof(exec_desc));
1196 exec_desc.dwSize = sizeof(exec_desc);
1197 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1198 exec_desc.dwBufferSize = 1024;
1199 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1201 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1202 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1203 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1204 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1205 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1206 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1207 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1208 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1209 emit_tquad(&ptr, 0);
1210 emit_end(&ptr);
1211 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
1212 inst_length -= sizeof(tquad);
1213 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1214 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1216 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1217 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1218 hr = IDirect3DDevice_BeginScene(device);
1219 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1220 set_execute_data(execute_buffer, 4, sizeof(tquad), inst_length);
1221 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1222 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1223 hr = IDirect3DDevice_EndScene(device);
1224 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1226 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1227 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1228 for (i = 0; i < 4; ++i)
1230 for (j = 0; j < 4; ++j)
1232 x = 80 * ((2 * j) + 1);
1233 y = 60 * ((2 * i) + 1);
1234 color = get_surface_color(rt, x, y);
1235 ok(compare_color(color, 0x0000ff00, 1),
1236 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1239 IDirectDrawSurface_Release(rt);
1241 destroy_viewport(device, viewport);
1242 IDirect3DExecuteBuffer_Release(execute_buffer);
1243 destroy_material(background);
1244 IDirect3DDevice_Release(device);
1245 IDirectDraw_Release(ddraw);
1246 DestroyWindow(window);
1249 static void test_ck_rgba(void)
1251 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1252 static D3DTLVERTEX tquad[] =
1254 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1255 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1256 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1257 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1258 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1259 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1260 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1261 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1263 /* Supposedly there was no D3DRENDERSTATE_COLORKEYENABLE in D3D < 5.
1264 * Maybe the WARP driver on Windows 8 ignores setting it via the older
1265 * device interface but it's buggy in that the internal state is not
1266 * initialized, or possibly toggling D3DRENDERSTATE_COLORKEYENABLE /
1267 * D3DRENDERSTATE_ALPHABLENDENABLE has unintended side effects.
1268 * Checking the W8 test results it seems like test 1 fails most of the time
1269 * and test 0 fails very rarely. */
1270 static const struct
1272 D3DCOLOR fill_color;
1273 BOOL color_key;
1274 BOOL blend;
1275 D3DCOLOR result1, result1_r200, result1_warp;
1276 D3DCOLOR result2, result2_r200, result2_warp;
1278 tests[] =
1280 /* r200 on Windows doesn't check the alpha component when applying the color
1281 * key, so the key matches on every texel. */
1282 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x0000ff00,
1283 0x000000ff, 0x000000ff, 0x0000ff00},
1284 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x0000ff00,
1285 0x000000ff, 0x000000ff, 0x0000ff00},
1286 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1287 0x0000ff00, 0x0000ff00, 0x0000ff00},
1288 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1289 0x0000ff00, 0x0000ff00, 0x0000ff00},
1290 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00,
1291 0x00807f00, 0x000000ff, 0x00807f00},
1292 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00,
1293 0x0000ff00, 0x000000ff, 0x0000ff00},
1294 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00,
1295 0x00807f00, 0x00807f00, 0x00807f00},
1296 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1297 0x0000ff00, 0x0000ff00, 0x0000ff00},
1300 IDirect3DExecuteBuffer *execute_buffer;
1301 D3DTEXTUREHANDLE texture_handle;
1302 D3DEXECUTEBUFFERDESC exec_desc;
1303 IDirect3DMaterial *background;
1304 IDirectDrawSurface *surface;
1305 IDirect3DViewport *viewport;
1306 DDSURFACEDESC surface_desc;
1307 IDirect3DTexture *texture;
1308 IDirect3DDevice *device;
1309 IDirectDrawSurface *rt;
1310 IDirectDraw *ddraw;
1311 D3DCOLOR color;
1312 HWND window;
1313 DDBLTFX fx;
1314 HRESULT hr;
1315 UINT i;
1317 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1318 0, 0, 640, 480, 0, 0, 0, 0);
1319 ddraw = create_ddraw();
1320 ok(!!ddraw, "Failed to create a ddraw object.\n");
1321 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1323 skip("Failed to create a 3D device, skipping test.\n");
1324 IDirectDraw_Release(ddraw);
1325 DestroyWindow(window);
1326 return;
1329 background = create_diffuse_material(device, 1.0, 0.0f, 0.0f, 1.0f);
1330 viewport = create_viewport(device, 0, 0, 640, 480);
1331 viewport_set_background(device, viewport, background);
1333 memset(&surface_desc, 0, sizeof(surface_desc));
1334 surface_desc.dwSize = sizeof(surface_desc);
1335 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1336 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1337 surface_desc.dwWidth = 256;
1338 surface_desc.dwHeight = 256;
1339 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1340 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1341 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1342 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1343 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1344 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1345 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1346 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1347 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1348 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1349 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1350 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1351 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1352 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1353 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1354 IDirect3DTexture_Release(texture);
1356 memset(&exec_desc, 0, sizeof(exec_desc));
1357 exec_desc.dwSize = sizeof(exec_desc);
1358 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1359 exec_desc.dwBufferSize = 1024;
1360 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1361 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1362 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1364 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1365 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1367 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1369 UINT draw1_len, draw2_len;
1370 void *ptr;
1372 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1373 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1374 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1375 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1376 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1377 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1378 emit_set_rs(&ptr, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1379 emit_set_rs(&ptr, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1380 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1381 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1382 emit_tquad(&ptr, 0);
1383 emit_end(&ptr);
1384 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - sizeof(tquad);
1385 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 4, 4);
1386 emit_tquad(&ptr, 0);
1387 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1388 emit_end(&ptr);
1389 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_len;
1390 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1391 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1393 memset(&fx, 0, sizeof(fx));
1394 fx.dwSize = sizeof(fx);
1395 U5(fx).dwFillColor = tests[i].fill_color;
1396 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1397 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1399 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1400 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1401 hr = IDirect3DDevice_BeginScene(device);
1402 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1403 set_execute_data(execute_buffer, 8, sizeof(tquad), draw1_len);
1404 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1405 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1406 hr = IDirect3DDevice_EndScene(device);
1407 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1409 color = get_surface_color(rt, 320, 240);
1410 ok(compare_color(color, tests[i].result1, 1)
1411 || broken(compare_color(color, tests[i].result1_r200, 1))
1412 || broken(compare_color(color, tests[i].result1_warp, 1)),
1413 "Got unexpected color 0x%08x for test %u.\n", color, i);
1415 U5(fx).dwFillColor = 0xff0000ff;
1416 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1417 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1419 hr = IDirect3DDevice_BeginScene(device);
1420 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1421 set_execute_data(execute_buffer, 8, sizeof(tquad) + draw1_len, draw2_len);
1422 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1423 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1424 hr = IDirect3DDevice_EndScene(device);
1425 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1427 /* This tests that fragments that are masked out by the color key are
1428 * discarded, instead of just fully transparent. */
1429 color = get_surface_color(rt, 320, 240);
1430 ok(compare_color(color, tests[i].result2, 1)
1431 || broken(compare_color(color, tests[i].result2_r200, 1))
1432 || broken(compare_color(color, tests[i].result2_warp, 1)),
1433 "Got unexpected color 0x%08x for test %u.\n", color, i);
1436 IDirectDrawSurface_Release(rt);
1437 IDirect3DExecuteBuffer_Release(execute_buffer);
1438 IDirectDrawSurface_Release(surface);
1439 destroy_viewport(device, viewport);
1440 destroy_material(background);
1441 IDirect3DDevice_Release(device);
1442 IDirectDraw_Release(ddraw);
1443 DestroyWindow(window);
1446 static void test_ck_default(void)
1448 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1449 static D3DTLVERTEX tquad[] =
1451 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1452 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1453 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1454 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1456 IDirect3DExecuteBuffer *execute_buffer;
1457 IDirectDrawSurface *surface, *rt;
1458 D3DTEXTUREHANDLE texture_handle;
1459 D3DEXECUTEBUFFERDESC exec_desc;
1460 IDirect3DMaterial *background;
1461 UINT draw1_offset, draw1_len;
1462 UINT draw2_offset, draw2_len;
1463 UINT draw3_offset, draw3_len;
1464 UINT draw4_offset, draw4_len;
1465 IDirect3DViewport *viewport;
1466 DDSURFACEDESC surface_desc;
1467 IDirect3DTexture *texture;
1468 IDirect3DDevice *device;
1469 IDirectDraw *ddraw;
1470 D3DCOLOR color;
1471 HWND window;
1472 DDBLTFX fx;
1473 HRESULT hr;
1474 void *ptr;
1476 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1477 0, 0, 640, 480, 0, 0, 0, 0);
1478 ddraw = create_ddraw();
1479 ok(!!ddraw, "Failed to create a ddraw object.\n");
1480 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1482 skip("Failed to create a 3D device, skipping test.\n");
1483 IDirectDraw_Release(ddraw);
1484 DestroyWindow(window);
1485 return;
1488 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1489 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1491 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
1492 viewport = create_viewport(device, 0, 0, 640, 480);
1493 viewport_set_background(device, viewport, background);
1495 memset(&surface_desc, 0, sizeof(surface_desc));
1496 surface_desc.dwSize = sizeof(surface_desc);
1497 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1498 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1499 surface_desc.dwWidth = 256;
1500 surface_desc.dwHeight = 256;
1501 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1502 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1503 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1504 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1505 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1506 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1507 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1508 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1509 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1510 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1511 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1512 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1513 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1514 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1515 IDirect3DTexture_Release(texture);
1517 memset(&fx, 0, sizeof(fx));
1518 fx.dwSize = sizeof(fx);
1519 U5(fx).dwFillColor = 0x000000ff;
1520 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1521 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1523 memset(&exec_desc, 0, sizeof(exec_desc));
1524 exec_desc.dwSize = sizeof(exec_desc);
1525 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1526 exec_desc.dwBufferSize = 1024;
1527 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1528 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1529 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1531 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1532 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1533 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1534 ptr = (BYTE *)exec_desc.lpData + sizeof(tquad);
1535 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1536 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1537 emit_tquad(&ptr, 0);
1538 emit_end(&ptr);
1539 draw1_offset = sizeof(tquad);
1540 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_offset;
1541 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1542 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, FALSE);
1543 emit_tquad(&ptr, 0);
1544 emit_end(&ptr);
1545 draw2_offset = draw1_offset + draw1_len;
1546 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw2_offset;
1547 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1548 emit_tquad(&ptr, 0);
1549 emit_end(&ptr);
1550 draw3_offset = draw2_offset + draw2_len;
1551 draw3_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw3_offset;
1552 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1553 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1554 emit_tquad(&ptr, 0);
1555 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1556 emit_end(&ptr);
1557 draw4_offset = draw3_offset + draw3_len;
1558 draw4_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw4_offset;
1559 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1560 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1562 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1563 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1564 hr = IDirect3DDevice_BeginScene(device);
1565 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1566 set_execute_data(execute_buffer, 4, draw1_offset, draw1_len);
1567 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1568 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1569 hr = IDirect3DDevice_EndScene(device);
1570 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1571 color = get_surface_color(rt, 320, 240);
1572 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1574 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1575 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1576 hr = IDirect3DDevice_BeginScene(device);
1577 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1578 set_execute_data(execute_buffer, 4, draw2_offset, draw2_len);
1579 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1580 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1581 hr = IDirect3DDevice_EndScene(device);
1582 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1583 color = get_surface_color(rt, 320, 240);
1584 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1586 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1587 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1588 hr = IDirect3DDevice_BeginScene(device);
1589 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1590 set_execute_data(execute_buffer, 4, draw3_offset, draw3_len);
1591 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1592 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1593 hr = IDirect3DDevice_EndScene(device);
1594 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1595 color = get_surface_color(rt, 320, 240);
1596 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1598 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1599 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1600 hr = IDirect3DDevice_BeginScene(device);
1601 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1602 set_execute_data(execute_buffer, 4, draw4_offset, draw4_len);
1603 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1604 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1605 hr = IDirect3DDevice_EndScene(device);
1606 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1607 color = get_surface_color(rt, 320, 240);
1608 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1610 IDirect3DExecuteBuffer_Release(execute_buffer);
1611 IDirectDrawSurface_Release(surface);
1612 destroy_viewport(device, viewport);
1613 destroy_material(background);
1614 IDirectDrawSurface_Release(rt);
1615 IDirect3DDevice_Release(device);
1616 IDirectDraw_Release(ddraw);
1617 DestroyWindow(window);
1620 static void test_ck_complex(void)
1622 IDirectDrawSurface *surface, *mipmap, *tmp;
1623 DDSCAPS caps = {DDSCAPS_COMPLEX};
1624 DDSURFACEDESC surface_desc;
1625 IDirect3DDevice *device;
1626 DDCOLORKEY color_key;
1627 IDirectDraw *ddraw;
1628 unsigned int i;
1629 ULONG refcount;
1630 HWND window;
1631 HRESULT hr;
1633 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1634 0, 0, 640, 480, 0, 0, 0, 0);
1635 ddraw = create_ddraw();
1636 ok(!!ddraw, "Failed to create a ddraw object.\n");
1637 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1639 skip("Failed to create a 3D device, skipping test.\n");
1640 DestroyWindow(window);
1641 IDirectDraw2_Release(ddraw);
1642 return;
1644 IDirect3DDevice_Release(device);
1646 memset(&surface_desc, 0, sizeof(surface_desc));
1647 surface_desc.dwSize = sizeof(surface_desc);
1648 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1649 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1650 surface_desc.dwWidth = 128;
1651 surface_desc.dwHeight = 128;
1652 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1653 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1655 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1656 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1657 color_key.dwColorSpaceLowValue = 0x0000ff00;
1658 color_key.dwColorSpaceHighValue = 0x0000ff00;
1659 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1660 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1661 memset(&color_key, 0, sizeof(color_key));
1662 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1663 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1664 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1665 color_key.dwColorSpaceLowValue);
1666 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1667 color_key.dwColorSpaceHighValue);
1669 mipmap = surface;
1670 IDirectDrawSurface_AddRef(mipmap);
1671 for (i = 0; i < 7; ++i)
1673 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1674 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1676 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1677 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1678 color_key.dwColorSpaceLowValue = 0x000000ff;
1679 color_key.dwColorSpaceHighValue = 0x000000ff;
1680 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1681 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x, i %u.\n", hr, i);
1682 memset(&color_key, 0, sizeof(color_key));
1683 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1684 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x, i %u.\n", hr, i);
1685 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1686 color_key.dwColorSpaceLowValue, i);
1687 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1688 color_key.dwColorSpaceHighValue, i);
1690 IDirectDrawSurface_Release(mipmap);
1691 mipmap = tmp;
1694 memset(&color_key, 0, sizeof(color_key));
1695 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1696 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1697 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1698 color_key.dwColorSpaceLowValue);
1699 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1700 color_key.dwColorSpaceHighValue);
1702 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1703 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1704 IDirectDrawSurface_Release(mipmap);
1705 refcount = IDirectDrawSurface_Release(surface);
1706 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1708 memset(&surface_desc, 0, sizeof(surface_desc));
1709 surface_desc.dwSize = sizeof(surface_desc);
1710 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1711 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1712 surface_desc.dwBackBufferCount = 1;
1713 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1714 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1716 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1717 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1718 color_key.dwColorSpaceLowValue = 0x0000ff00;
1719 color_key.dwColorSpaceHighValue = 0x0000ff00;
1720 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1721 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1722 memset(&color_key, 0, sizeof(color_key));
1723 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1724 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1725 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1726 color_key.dwColorSpaceLowValue);
1727 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1728 color_key.dwColorSpaceHighValue);
1730 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
1731 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1733 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1734 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1735 color_key.dwColorSpaceLowValue = 0x0000ff00;
1736 color_key.dwColorSpaceHighValue = 0x0000ff00;
1737 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1738 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1739 memset(&color_key, 0, sizeof(color_key));
1740 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1741 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1742 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1743 color_key.dwColorSpaceLowValue);
1744 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1745 color_key.dwColorSpaceHighValue);
1747 IDirectDrawSurface_Release(tmp);
1749 refcount = IDirectDrawSurface_Release(surface);
1750 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1751 refcount = IDirectDraw_Release(ddraw);
1752 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1753 DestroyWindow(window);
1756 struct qi_test
1758 REFIID iid;
1759 REFIID refcount_iid;
1760 HRESULT hr;
1763 static void test_qi(const char *test_name, IUnknown *base_iface,
1764 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1766 ULONG refcount, expected_refcount;
1767 IUnknown *iface1, *iface2;
1768 HRESULT hr;
1769 UINT i, j;
1771 for (i = 0; i < entry_count; ++i)
1773 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1774 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1775 if (SUCCEEDED(hr))
1777 for (j = 0; j < entry_count; ++j)
1779 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1780 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1781 if (SUCCEEDED(hr))
1783 expected_refcount = 0;
1784 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1785 ++expected_refcount;
1786 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1787 ++expected_refcount;
1788 refcount = IUnknown_Release(iface2);
1789 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1790 refcount, test_name, i, j, expected_refcount);
1794 expected_refcount = 0;
1795 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1796 ++expected_refcount;
1797 refcount = IUnknown_Release(iface1);
1798 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1799 refcount, test_name, i, expected_refcount);
1804 static void test_surface_qi(void)
1806 static const struct qi_test tests[] =
1808 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1809 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1810 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1811 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1812 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1813 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1814 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1815 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1816 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1817 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1818 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1819 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1820 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1821 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1822 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1823 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1824 {&IID_IDirect3D, NULL, E_INVALIDARG },
1825 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1826 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1827 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1828 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1829 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1830 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1831 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1832 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1833 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1834 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1835 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1836 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1837 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1838 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1839 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1840 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1841 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1842 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1845 IDirectDrawSurface *surface;
1846 DDSURFACEDESC surface_desc;
1847 IDirect3DDevice *device;
1848 IDirectDraw *ddraw;
1849 HWND window;
1850 HRESULT hr;
1852 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1854 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1855 return;
1858 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1859 0, 0, 640, 480, 0, 0, 0, 0);
1860 ddraw = create_ddraw();
1861 ok(!!ddraw, "Failed to create a ddraw object.\n");
1862 /* Try to create a D3D device to see if the ddraw implementation supports
1863 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1864 * doesn't support e.g. the IDirect3DTexture interfaces. */
1865 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1867 skip("Failed to create a 3D device, skipping test.\n");
1868 IDirectDraw_Release(ddraw);
1869 DestroyWindow(window);
1870 return;
1872 IDirect3DDevice_Release(device);
1874 memset(&surface_desc, 0, sizeof(surface_desc));
1875 surface_desc.dwSize = sizeof(surface_desc);
1876 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1877 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1878 surface_desc.dwWidth = 512;
1879 surface_desc.dwHeight = 512;
1880 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1881 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1883 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1885 IDirectDrawSurface_Release(surface);
1886 IDirectDraw_Release(ddraw);
1887 DestroyWindow(window);
1890 static void test_device_qi(void)
1892 static const struct qi_test tests[] =
1894 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1895 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1896 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1897 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1898 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1899 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1900 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1901 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1902 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1903 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1904 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1905 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1906 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1907 {&IID_IDirect3DHALDevice, &IID_IDirectDrawSurface, S_OK },
1908 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1909 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1910 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1911 {&IID_IDirect3D, NULL, E_INVALIDARG },
1912 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1913 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1914 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1915 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1916 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1917 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1918 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1919 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1920 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1921 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1922 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1923 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1924 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1925 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1926 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1927 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1928 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1929 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1933 IDirect3DDevice *device;
1934 IDirectDraw *ddraw;
1935 HWND window;
1937 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1939 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1940 return;
1943 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1944 0, 0, 640, 480, 0, 0, 0, 0);
1945 ddraw = create_ddraw();
1946 ok(!!ddraw, "Failed to create a ddraw object.\n");
1947 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1949 skip("Failed to create a 3D device, skipping test.\n");
1950 IDirectDraw_Release(ddraw);
1951 DestroyWindow(window);
1952 return;
1955 test_qi("device_qi", (IUnknown *)device, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1957 IDirect3DDevice_Release(device);
1958 IDirectDraw_Release(ddraw);
1959 DestroyWindow(window);
1962 static void test_wndproc(void)
1964 LONG_PTR proc, ddraw_proc;
1965 IDirectDraw *ddraw;
1966 WNDCLASSA wc = {0};
1967 HWND window;
1968 HRESULT hr;
1969 ULONG ref;
1971 static struct message messages[] =
1973 {WM_WINDOWPOSCHANGING, FALSE, 0},
1974 {WM_MOVE, FALSE, 0},
1975 {WM_SIZE, FALSE, 0},
1976 {WM_WINDOWPOSCHANGING, FALSE, 0},
1977 {WM_ACTIVATE, FALSE, 0},
1978 {WM_SETFOCUS, FALSE, 0},
1979 {0, FALSE, 0},
1982 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
1983 ddraw = create_ddraw();
1984 ok(!!ddraw, "Failed to create a ddraw object.\n");
1986 wc.lpfnWndProc = test_proc;
1987 wc.lpszClassName = "ddraw_test_wndproc_wc";
1988 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1990 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
1991 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
1993 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1994 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1995 (LONG_PTR)test_proc, proc);
1996 expect_messages = messages;
1997 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1998 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1999 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2000 expect_messages = NULL;
2001 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2002 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2003 (LONG_PTR)test_proc, proc);
2004 ref = IDirectDraw_Release(ddraw);
2005 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2006 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2007 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2008 (LONG_PTR)test_proc, proc);
2010 /* DDSCL_NORMAL doesn't. */
2011 ddraw = create_ddraw();
2012 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2013 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2014 (LONG_PTR)test_proc, proc);
2015 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2016 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2017 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2018 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2019 (LONG_PTR)test_proc, proc);
2020 ref = IDirectDraw_Release(ddraw);
2021 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2022 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2023 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2024 (LONG_PTR)test_proc, proc);
2026 /* The original window proc is only restored by ddraw if the current
2027 * window proc matches the one ddraw set. This also affects switching
2028 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2029 ddraw = create_ddraw();
2030 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2031 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2032 (LONG_PTR)test_proc, proc);
2033 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2034 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2035 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2036 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2037 (LONG_PTR)test_proc, proc);
2038 ddraw_proc = proc;
2039 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2040 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2041 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2042 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2043 (LONG_PTR)test_proc, proc);
2044 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2045 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2046 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2047 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2048 (LONG_PTR)test_proc, proc);
2049 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2050 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2051 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2052 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2053 (LONG_PTR)DefWindowProcA, proc);
2054 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2055 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2056 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
2057 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2058 (LONG_PTR)DefWindowProcA, proc);
2059 ref = IDirectDraw_Release(ddraw);
2060 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2061 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2062 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2063 (LONG_PTR)test_proc, proc);
2065 ddraw = create_ddraw();
2066 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2067 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2068 (LONG_PTR)test_proc, proc);
2069 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2070 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2071 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2072 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2073 (LONG_PTR)test_proc, proc);
2074 ref = IDirectDraw_Release(ddraw);
2075 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2076 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2077 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2078 (LONG_PTR)DefWindowProcA, proc);
2080 fix_wndproc(window, (LONG_PTR)test_proc);
2081 expect_messages = NULL;
2082 DestroyWindow(window);
2083 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2086 static void test_window_style(void)
2088 LONG style, exstyle, tmp, expected_style;
2089 RECT fullscreen_rect, r;
2090 IDirectDraw *ddraw;
2091 HWND window;
2092 HRESULT hr;
2093 ULONG ref;
2094 BOOL ret;
2096 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2097 0, 0, 100, 100, 0, 0, 0, 0);
2098 ddraw = create_ddraw();
2099 ok(!!ddraw, "Failed to create a ddraw object.\n");
2101 style = GetWindowLongA(window, GWL_STYLE);
2102 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2103 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2105 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2106 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2108 tmp = GetWindowLongA(window, GWL_STYLE);
2109 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2110 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2111 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2113 GetWindowRect(window, &r);
2114 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2115 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2116 GetClientRect(window, &r);
2117 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2119 ret = SetForegroundWindow(GetDesktopWindow());
2120 ok(ret, "Failed to set foreground window.\n");
2122 tmp = GetWindowLongA(window, GWL_STYLE);
2123 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2124 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2125 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2127 ret = SetForegroundWindow(window);
2128 ok(ret, "Failed to set foreground window.\n");
2129 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2130 * the next tests expect this. */
2131 ShowWindow(window, SW_HIDE);
2133 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2134 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2136 tmp = GetWindowLongA(window, GWL_STYLE);
2137 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2138 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2139 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2141 ShowWindow(window, SW_SHOW);
2142 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2143 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2145 tmp = GetWindowLongA(window, GWL_STYLE);
2146 expected_style = style | WS_VISIBLE;
2147 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2148 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2149 expected_style = exstyle | WS_EX_TOPMOST;
2150 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2152 ret = SetForegroundWindow(GetDesktopWindow());
2153 ok(ret, "Failed to set foreground window.\n");
2154 tmp = GetWindowLongA(window, GWL_STYLE);
2155 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2156 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2157 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2158 expected_style = exstyle | WS_EX_TOPMOST;
2159 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2161 ref = IDirectDraw_Release(ddraw);
2162 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2164 DestroyWindow(window);
2167 static void test_redundant_mode_set(void)
2169 DDSURFACEDESC surface_desc = {0};
2170 IDirectDraw *ddraw;
2171 HWND window;
2172 HRESULT hr;
2173 RECT r, s;
2174 ULONG ref;
2176 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2177 0, 0, 100, 100, 0, 0, 0, 0);
2178 ddraw = create_ddraw();
2179 ok(!!ddraw, "Failed to create a ddraw object.\n");
2181 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2182 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2184 surface_desc.dwSize = sizeof(surface_desc);
2185 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
2186 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
2188 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2189 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
2190 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2192 GetWindowRect(window, &r);
2193 r.right /= 2;
2194 r.bottom /= 2;
2195 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2196 GetWindowRect(window, &s);
2197 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2199 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2200 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
2201 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2203 GetWindowRect(window, &s);
2204 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2206 ref = IDirectDraw_Release(ddraw);
2207 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2209 DestroyWindow(window);
2212 static SIZE screen_size;
2214 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2216 if (message == WM_SIZE)
2218 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2219 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2222 return test_proc(hwnd, message, wparam, lparam);
2225 struct test_coop_level_mode_set_enum_param
2227 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2230 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC *surface_desc, void *context)
2232 struct test_coop_level_mode_set_enum_param *param = context;
2234 if (U1(surface_desc->ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2235 return DDENUMRET_OK;
2236 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2237 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2238 return DDENUMRET_OK;
2240 if (!param->ddraw_width)
2242 param->ddraw_width = surface_desc->dwWidth;
2243 param->ddraw_height = surface_desc->dwHeight;
2244 return DDENUMRET_OK;
2246 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2247 return DDENUMRET_OK;
2249 param->user32_width = surface_desc->dwWidth;
2250 param->user32_height = surface_desc->dwHeight;
2251 return DDENUMRET_CANCEL;
2254 static void test_coop_level_mode_set(void)
2256 IDirectDrawSurface *primary;
2257 RECT registry_rect, ddraw_rect, user32_rect, r;
2258 IDirectDraw *ddraw;
2259 DDSURFACEDESC ddsd;
2260 WNDCLASSA wc = {0};
2261 HWND window;
2262 HRESULT hr;
2263 ULONG ref;
2264 MSG msg;
2265 struct test_coop_level_mode_set_enum_param param;
2266 DEVMODEW devmode;
2267 BOOL ret;
2268 LONG change_ret;
2270 static const struct message exclusive_messages[] =
2272 {WM_WINDOWPOSCHANGING, FALSE, 0},
2273 {WM_WINDOWPOSCHANGED, FALSE, 0},
2274 {WM_SIZE, FALSE, 0},
2275 {WM_DISPLAYCHANGE, FALSE, 0},
2276 {0, FALSE, 0},
2278 static const struct message exclusive_focus_loss_messages[] =
2280 {WM_ACTIVATE, TRUE, WA_INACTIVE},
2281 {WM_DISPLAYCHANGE, FALSE, 0},
2282 {WM_WINDOWPOSCHANGING, FALSE, 0},
2283 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2284 * SW_MINIMIZED, causing a recursive window activation that does not
2285 * produce the same result in Wine yet. Ignore the difference for now.
2286 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2287 {WM_WINDOWPOSCHANGED, FALSE, 0},
2288 {WM_MOVE, FALSE, 0},
2289 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2290 {WM_ACTIVATEAPP, TRUE, FALSE},
2291 {0, FALSE, 0},
2293 static const struct message exclusive_focus_restore_messages[] =
2295 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2296 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2297 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2298 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2299 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2300 /* Native redundantly sets the window size here. */
2301 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2302 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2303 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2304 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2305 {0, FALSE, 0},
2307 static const struct message sc_restore_messages[] =
2309 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2310 {WM_WINDOWPOSCHANGING, FALSE, 0},
2311 {WM_WINDOWPOSCHANGED, FALSE, 0},
2312 {WM_SIZE, TRUE, SIZE_RESTORED},
2313 {0, FALSE, 0},
2315 static const struct message sc_minimize_messages[] =
2317 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2318 {WM_WINDOWPOSCHANGING, FALSE, 0},
2319 {WM_WINDOWPOSCHANGED, FALSE, 0},
2320 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2321 {0, FALSE, 0},
2323 static const struct message sc_maximize_messages[] =
2325 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2326 {WM_WINDOWPOSCHANGING, FALSE, 0},
2327 {WM_WINDOWPOSCHANGED, FALSE, 0},
2328 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2329 {0, FALSE, 0},
2332 static const struct message normal_messages[] =
2334 {WM_DISPLAYCHANGE, FALSE, 0},
2335 {0, FALSE, 0},
2338 ddraw = create_ddraw();
2339 ok(!!ddraw, "Failed to create a ddraw object.\n");
2341 memset(&param, 0, sizeof(param));
2342 hr = IDirectDraw_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2343 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2344 ref = IDirectDraw_Release(ddraw);
2345 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2347 if (!param.user32_height)
2349 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2350 return;
2353 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2354 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2355 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2357 memset(&devmode, 0, sizeof(devmode));
2358 devmode.dmSize = sizeof(devmode);
2359 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2360 devmode.dmPelsWidth = param.user32_width;
2361 devmode.dmPelsHeight = param.user32_height;
2362 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2363 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2365 ddraw = create_ddraw();
2366 ok(!!ddraw, "Failed to create a ddraw object.\n");
2368 wc.lpfnWndProc = mode_set_proc;
2369 wc.lpszClassName = "ddraw_test_wndproc_wc";
2370 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2372 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2373 0, 0, 100, 100, 0, 0, 0, 0);
2375 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2376 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2378 GetWindowRect(window, &r);
2379 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2380 wine_dbgstr_rect(&r));
2382 memset(&ddsd, 0, sizeof(ddsd));
2383 ddsd.dwSize = sizeof(ddsd);
2384 ddsd.dwFlags = DDSD_CAPS;
2385 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2387 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2388 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2389 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2390 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2391 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2392 param.user32_width, ddsd.dwWidth);
2393 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2394 param.user32_height, ddsd.dwHeight);
2396 GetWindowRect(window, &r);
2397 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2398 wine_dbgstr_rect(&r));
2400 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2401 expect_messages = exclusive_messages;
2402 screen_size.cx = 0;
2403 screen_size.cy = 0;
2405 hr = IDirectDrawSurface_IsLost(primary);
2406 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2407 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2408 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2409 hr = IDirectDrawSurface_IsLost(primary);
2410 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2412 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2413 expect_messages = NULL;
2414 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2415 "Expected screen size %ux%u, got %ux%u.\n",
2416 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2418 GetWindowRect(window, &r);
2419 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2420 wine_dbgstr_rect(&r));
2422 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2423 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2424 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2425 param.user32_width, ddsd.dwWidth);
2426 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2427 param.user32_height, ddsd.dwHeight);
2428 IDirectDrawSurface_Release(primary);
2430 memset(&ddsd, 0, sizeof(ddsd));
2431 ddsd.dwSize = sizeof(ddsd);
2432 ddsd.dwFlags = DDSD_CAPS;
2433 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2435 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2436 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2437 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2438 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2439 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2440 param.ddraw_width, ddsd.dwWidth);
2441 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2442 param.ddraw_height, ddsd.dwHeight);
2444 GetWindowRect(window, &r);
2445 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2446 wine_dbgstr_rect(&r));
2448 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2449 expect_messages = exclusive_messages;
2450 screen_size.cx = 0;
2451 screen_size.cy = 0;
2453 hr = IDirectDrawSurface_IsLost(primary);
2454 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2455 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2456 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2457 hr = IDirectDrawSurface_IsLost(primary);
2458 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2460 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2461 expect_messages = NULL;
2462 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2463 "Expected screen size %ux%u, got %ux%u.\n",
2464 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2466 GetWindowRect(window, &r);
2467 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2468 wine_dbgstr_rect(&r));
2470 expect_messages = exclusive_focus_loss_messages;
2471 ret = SetForegroundWindow(GetDesktopWindow());
2472 ok(ret, "Failed to set foreground window.\n");
2473 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2474 memset(&devmode, 0, sizeof(devmode));
2475 devmode.dmSize = sizeof(devmode);
2476 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2477 ok(ret, "Failed to get display mode.\n");
2478 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2479 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2480 devmode.dmPelsWidth, devmode.dmPelsHeight);
2482 expect_messages = exclusive_focus_restore_messages;
2483 ShowWindow(window, SW_RESTORE);
2484 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2486 GetWindowRect(window, &r);
2487 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2488 wine_dbgstr_rect(&r));
2489 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2490 ok(ret, "Failed to get display mode.\n");
2491 ok(devmode.dmPelsWidth == param.ddraw_width
2492 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpect screen size %ux%u.\n",
2493 devmode.dmPelsWidth, devmode.dmPelsHeight);
2495 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2496 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2497 /* Normally the primary should be restored here. Unfortunately this causes the
2498 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
2499 * testbot. Another Restore call would presumably avoid the crash, but it also moots
2500 * the point of the GetSurfaceDesc call. */
2502 expect_messages = sc_minimize_messages;
2503 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2504 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2505 expect_messages = NULL;
2507 expect_messages = sc_restore_messages;
2508 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
2509 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2510 expect_messages = NULL;
2512 expect_messages = sc_maximize_messages;
2513 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2514 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2515 expect_messages = NULL;
2517 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2518 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2520 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2521 expect_messages = exclusive_messages;
2522 screen_size.cx = 0;
2523 screen_size.cy = 0;
2525 hr = IDirectDrawSurface_IsLost(primary);
2526 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2527 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2528 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2529 hr = IDirectDrawSurface_IsLost(primary);
2530 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2532 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2533 expect_messages = NULL;
2534 ok(screen_size.cx == registry_mode.dmPelsWidth
2535 && screen_size.cy == registry_mode.dmPelsHeight,
2536 "Expected screen size %ux%u, got %ux%u.\n",
2537 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
2539 GetWindowRect(window, &r);
2540 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2541 wine_dbgstr_rect(&r));
2543 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2544 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2545 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2546 param.ddraw_width, ddsd.dwWidth);
2547 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2548 param.ddraw_height, ddsd.dwHeight);
2549 IDirectDrawSurface_Release(primary);
2551 /* For Wine. */
2552 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2553 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2555 memset(&ddsd, 0, sizeof(ddsd));
2556 ddsd.dwSize = sizeof(ddsd);
2557 ddsd.dwFlags = DDSD_CAPS;
2558 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2560 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2561 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2562 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2563 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2564 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2565 registry_mode.dmPelsWidth, ddsd.dwWidth);
2566 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2567 registry_mode.dmPelsHeight, ddsd.dwHeight);
2569 GetWindowRect(window, &r);
2570 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2571 wine_dbgstr_rect(&r));
2573 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2574 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2576 GetWindowRect(window, &r);
2577 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2578 wine_dbgstr_rect(&r));
2580 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2581 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2582 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2583 registry_mode.dmPelsWidth, ddsd.dwWidth);
2584 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2585 registry_mode.dmPelsHeight, ddsd.dwHeight);
2586 IDirectDrawSurface_Release(primary);
2588 memset(&ddsd, 0, sizeof(ddsd));
2589 ddsd.dwSize = sizeof(ddsd);
2590 ddsd.dwFlags = DDSD_CAPS;
2591 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2593 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2594 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2595 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2596 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2597 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2598 registry_mode.dmPelsWidth, ddsd.dwWidth);
2599 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2600 registry_mode.dmPelsHeight, ddsd.dwHeight);
2602 GetWindowRect(window, &r);
2603 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2604 wine_dbgstr_rect(&r));
2606 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2607 expect_messages = normal_messages;
2608 screen_size.cx = 0;
2609 screen_size.cy = 0;
2611 hr = IDirectDrawSurface_IsLost(primary);
2612 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2613 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2614 devmode.dmPelsWidth = param.user32_width;
2615 devmode.dmPelsHeight = param.user32_height;
2616 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2617 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2618 hr = IDirectDrawSurface_IsLost(primary);
2619 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2621 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2622 expect_messages = NULL;
2623 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2625 GetWindowRect(window, &r);
2626 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2627 wine_dbgstr_rect(&r));
2629 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2630 expect_messages = normal_messages;
2631 screen_size.cx = 0;
2632 screen_size.cy = 0;
2634 hr = IDirectDrawSurface_Restore(primary);
2635 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2636 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2637 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
2639 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
2640 IDirectDrawSurface_Release(primary);
2641 IDirectDraw_Release(ddraw);
2642 goto done;
2644 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2645 hr = IDirectDrawSurface_Restore(primary);
2646 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2647 hr = IDirectDrawSurface_IsLost(primary);
2648 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2650 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2651 expect_messages = NULL;
2652 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2654 GetWindowRect(window, &r);
2655 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2656 wine_dbgstr_rect(&r));
2658 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2659 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2660 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2661 registry_mode.dmPelsWidth, ddsd.dwWidth);
2662 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2663 registry_mode.dmPelsHeight, ddsd.dwHeight);
2664 IDirectDrawSurface_Release(primary);
2666 memset(&ddsd, 0, sizeof(ddsd));
2667 ddsd.dwSize = sizeof(ddsd);
2668 ddsd.dwFlags = DDSD_CAPS;
2669 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2671 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2672 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2673 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2674 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2675 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2676 param.ddraw_width, ddsd.dwWidth);
2677 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2678 param.ddraw_height, ddsd.dwHeight);
2680 GetWindowRect(window, &r);
2681 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2682 wine_dbgstr_rect(&r));
2684 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2685 expect_messages = normal_messages;
2686 screen_size.cx = 0;
2687 screen_size.cy = 0;
2689 hr = IDirectDrawSurface_IsLost(primary);
2690 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2691 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2692 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2693 hr = IDirectDrawSurface_IsLost(primary);
2694 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2696 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2697 expect_messages = NULL;
2698 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2700 GetWindowRect(window, &r);
2701 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2702 wine_dbgstr_rect(&r));
2704 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2705 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2706 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2707 param.ddraw_width, ddsd.dwWidth);
2708 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2709 param.ddraw_height, ddsd.dwHeight);
2710 IDirectDrawSurface_Release(primary);
2712 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2713 ok(ret, "Failed to get display mode.\n");
2714 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2715 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
2716 "Expected resolution %ux%u, got %ux%u.\n",
2717 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
2718 devmode.dmPelsWidth, devmode.dmPelsHeight);
2719 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2720 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2722 memset(&ddsd, 0, sizeof(ddsd));
2723 ddsd.dwSize = sizeof(ddsd);
2724 ddsd.dwFlags = DDSD_CAPS;
2725 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2727 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2728 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2729 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2730 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2731 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2732 registry_mode.dmPelsWidth, ddsd.dwWidth);
2733 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2734 registry_mode.dmPelsHeight, ddsd.dwHeight);
2736 GetWindowRect(window, &r);
2737 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2738 wine_dbgstr_rect(&r));
2740 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2741 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2742 * not DDSCL_FULLSCREEN. */
2743 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2744 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2746 GetWindowRect(window, &r);
2747 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2748 wine_dbgstr_rect(&r));
2750 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2751 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2752 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2753 registry_mode.dmPelsWidth, ddsd.dwWidth);
2754 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2755 registry_mode.dmPelsHeight, ddsd.dwHeight);
2756 IDirectDrawSurface_Release(primary);
2758 memset(&ddsd, 0, sizeof(ddsd));
2759 ddsd.dwSize = sizeof(ddsd);
2760 ddsd.dwFlags = DDSD_CAPS;
2761 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2763 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2764 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2765 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2766 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2767 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2768 registry_mode.dmPelsWidth, ddsd.dwWidth);
2769 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2770 registry_mode.dmPelsHeight, ddsd.dwHeight);
2772 GetWindowRect(window, &r);
2773 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2774 wine_dbgstr_rect(&r));
2776 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2777 expect_messages = normal_messages;
2778 screen_size.cx = 0;
2779 screen_size.cy = 0;
2781 hr = IDirectDrawSurface_IsLost(primary);
2782 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2783 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2784 devmode.dmPelsWidth = param.user32_width;
2785 devmode.dmPelsHeight = param.user32_height;
2786 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2787 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2788 hr = IDirectDrawSurface_IsLost(primary);
2789 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2791 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2792 expect_messages = NULL;
2793 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2795 GetWindowRect(window, &r);
2796 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2797 wine_dbgstr_rect(&r));
2799 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2800 expect_messages = normal_messages;
2801 screen_size.cx = 0;
2802 screen_size.cy = 0;
2804 hr = IDirectDrawSurface_Restore(primary);
2805 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2806 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2807 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2808 hr = IDirectDrawSurface_Restore(primary);
2809 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2810 hr = IDirectDrawSurface_IsLost(primary);
2811 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2813 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2814 expect_messages = NULL;
2815 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2817 GetWindowRect(window, &r);
2818 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2819 wine_dbgstr_rect(&r));
2821 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2822 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2823 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2824 registry_mode.dmPelsWidth, ddsd.dwWidth);
2825 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2826 registry_mode.dmPelsHeight, ddsd.dwHeight);
2827 IDirectDrawSurface_Release(primary);
2829 memset(&ddsd, 0, sizeof(ddsd));
2830 ddsd.dwSize = sizeof(ddsd);
2831 ddsd.dwFlags = DDSD_CAPS;
2832 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2834 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2835 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2836 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2837 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2838 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2839 param.ddraw_width, ddsd.dwWidth);
2840 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2841 param.ddraw_height, ddsd.dwHeight);
2843 GetWindowRect(window, &r);
2844 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2845 wine_dbgstr_rect(&r));
2847 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2848 expect_messages = normal_messages;
2849 screen_size.cx = 0;
2850 screen_size.cy = 0;
2852 hr = IDirectDrawSurface_IsLost(primary);
2853 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2854 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2855 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2856 hr = IDirectDrawSurface_IsLost(primary);
2857 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2859 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2860 expect_messages = NULL;
2861 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2863 GetWindowRect(window, &r);
2864 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2865 wine_dbgstr_rect(&r));
2867 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2868 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2869 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2870 param.ddraw_width, ddsd.dwWidth);
2871 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2872 param.ddraw_height, ddsd.dwHeight);
2873 IDirectDrawSurface_Release(primary);
2875 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2876 ok(ret, "Failed to get display mode.\n");
2877 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2878 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
2879 "Expected resolution %ux%u, got %ux%u.\n",
2880 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
2881 devmode.dmPelsWidth, devmode.dmPelsHeight);
2882 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2883 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2885 memset(&ddsd, 0, sizeof(ddsd));
2886 ddsd.dwSize = sizeof(ddsd);
2887 ddsd.dwFlags = DDSD_CAPS;
2888 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2890 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2891 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2892 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2893 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2894 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2895 registry_mode.dmPelsWidth, ddsd.dwWidth);
2896 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2897 registry_mode.dmPelsHeight, ddsd.dwHeight);
2898 IDirectDrawSurface_Release(primary);
2900 GetWindowRect(window, &r);
2901 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2902 wine_dbgstr_rect(&r));
2904 /* Unlike ddraw2-7, changing from EXCLUSIVE to NORMAL does not restore the resolution */
2905 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2906 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2907 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2908 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2910 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2911 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2913 memset(&ddsd, 0, sizeof(ddsd));
2914 ddsd.dwSize = sizeof(ddsd);
2915 ddsd.dwFlags = DDSD_CAPS;
2916 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2918 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2919 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2920 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2921 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2922 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2923 param.ddraw_width, ddsd.dwWidth);
2924 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2925 param.ddraw_height, ddsd.dwHeight);
2926 IDirectDrawSurface_Release(primary);
2927 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2928 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2930 ref = IDirectDraw_Release(ddraw);
2931 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2933 GetWindowRect(window, &r);
2934 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2935 wine_dbgstr_rect(&r));
2937 done:
2938 expect_messages = NULL;
2939 DestroyWindow(window);
2940 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2943 static void test_coop_level_mode_set_multi(void)
2945 IDirectDraw *ddraw1, *ddraw2;
2946 UINT w, h;
2947 HWND window;
2948 HRESULT hr;
2949 ULONG ref;
2951 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2952 0, 0, 100, 100, 0, 0, 0, 0);
2953 ddraw1 = create_ddraw();
2954 ok(!!ddraw1, "Failed to create a ddraw object.\n");
2956 /* With just a single ddraw object, the display mode is restored on
2957 * release. */
2958 hr = set_display_mode(ddraw1, 800, 600);
2959 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
2961 win_skip("Broken SetDisplayMode(), skipping test.\n");
2962 IDirectDraw_Release(ddraw1);
2963 DestroyWindow(window);
2964 return;
2966 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2967 w = GetSystemMetrics(SM_CXSCREEN);
2968 ok(w == 800, "Got unexpected screen width %u.\n", w);
2969 h = GetSystemMetrics(SM_CYSCREEN);
2970 ok(h == 600, "Got unexpected screen height %u.\n", h);
2972 ref = IDirectDraw_Release(ddraw1);
2973 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2974 w = GetSystemMetrics(SM_CXSCREEN);
2975 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
2976 h = GetSystemMetrics(SM_CYSCREEN);
2977 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
2979 /* When there are multiple ddraw objects, the display mode is restored to
2980 * the initial mode, before the first SetDisplayMode() call. */
2981 ddraw1 = create_ddraw();
2982 hr = set_display_mode(ddraw1, 800, 600);
2983 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2984 w = GetSystemMetrics(SM_CXSCREEN);
2985 ok(w == 800, "Got unexpected screen width %u.\n", w);
2986 h = GetSystemMetrics(SM_CYSCREEN);
2987 ok(h == 600, "Got unexpected screen height %u.\n", h);
2989 ddraw2 = create_ddraw();
2990 hr = set_display_mode(ddraw2, 640, 480);
2991 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2992 w = GetSystemMetrics(SM_CXSCREEN);
2993 ok(w == 640, "Got unexpected screen width %u.\n", w);
2994 h = GetSystemMetrics(SM_CYSCREEN);
2995 ok(h == 480, "Got unexpected screen height %u.\n", h);
2997 ref = IDirectDraw_Release(ddraw2);
2998 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2999 w = GetSystemMetrics(SM_CXSCREEN);
3000 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3001 h = GetSystemMetrics(SM_CYSCREEN);
3002 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3004 ref = IDirectDraw_Release(ddraw1);
3005 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3006 w = GetSystemMetrics(SM_CXSCREEN);
3007 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3008 h = GetSystemMetrics(SM_CYSCREEN);
3009 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3011 /* Regardless of release ordering. */
3012 ddraw1 = create_ddraw();
3013 hr = set_display_mode(ddraw1, 800, 600);
3014 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3015 w = GetSystemMetrics(SM_CXSCREEN);
3016 ok(w == 800, "Got unexpected screen width %u.\n", w);
3017 h = GetSystemMetrics(SM_CYSCREEN);
3018 ok(h == 600, "Got unexpected screen height %u.\n", h);
3020 ddraw2 = create_ddraw();
3021 hr = set_display_mode(ddraw2, 640, 480);
3022 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3023 w = GetSystemMetrics(SM_CXSCREEN);
3024 ok(w == 640, "Got unexpected screen width %u.\n", w);
3025 h = GetSystemMetrics(SM_CYSCREEN);
3026 ok(h == 480, "Got unexpected screen height %u.\n", h);
3028 ref = IDirectDraw_Release(ddraw1);
3029 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3030 w = GetSystemMetrics(SM_CXSCREEN);
3031 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3032 h = GetSystemMetrics(SM_CYSCREEN);
3033 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3035 ref = IDirectDraw_Release(ddraw2);
3036 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3037 w = GetSystemMetrics(SM_CXSCREEN);
3038 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3039 h = GetSystemMetrics(SM_CYSCREEN);
3040 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3042 /* But only for ddraw objects that called SetDisplayMode(). */
3043 ddraw1 = create_ddraw();
3044 ddraw2 = create_ddraw();
3045 hr = set_display_mode(ddraw2, 640, 480);
3046 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3047 w = GetSystemMetrics(SM_CXSCREEN);
3048 ok(w == 640, "Got unexpected screen width %u.\n", w);
3049 h = GetSystemMetrics(SM_CYSCREEN);
3050 ok(h == 480, "Got unexpected screen height %u.\n", h);
3052 ref = IDirectDraw_Release(ddraw1);
3053 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3054 w = GetSystemMetrics(SM_CXSCREEN);
3055 ok(w == 640, "Got unexpected screen width %u.\n", w);
3056 h = GetSystemMetrics(SM_CYSCREEN);
3057 ok(h == 480, "Got unexpected screen height %u.\n", h);
3059 ref = IDirectDraw_Release(ddraw2);
3060 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3061 w = GetSystemMetrics(SM_CXSCREEN);
3062 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3063 h = GetSystemMetrics(SM_CYSCREEN);
3064 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3066 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3067 * restoring the display mode. */
3068 ddraw1 = create_ddraw();
3069 hr = set_display_mode(ddraw1, 800, 600);
3070 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3071 w = GetSystemMetrics(SM_CXSCREEN);
3072 ok(w == 800, "Got unexpected screen width %u.\n", w);
3073 h = GetSystemMetrics(SM_CYSCREEN);
3074 ok(h == 600, "Got unexpected screen height %u.\n", h);
3076 ddraw2 = create_ddraw();
3077 hr = set_display_mode(ddraw2, 640, 480);
3078 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3079 w = GetSystemMetrics(SM_CXSCREEN);
3080 ok(w == 640, "Got unexpected screen width %u.\n", w);
3081 h = GetSystemMetrics(SM_CYSCREEN);
3082 ok(h == 480, "Got unexpected screen height %u.\n", h);
3084 hr = IDirectDraw_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3085 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3087 ref = IDirectDraw_Release(ddraw1);
3088 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3089 w = GetSystemMetrics(SM_CXSCREEN);
3090 ok(w == 640, "Got unexpected screen width %u.\n", w);
3091 h = GetSystemMetrics(SM_CYSCREEN);
3092 ok(h == 480, "Got unexpected screen height %u.\n", h);
3094 ref = IDirectDraw_Release(ddraw2);
3095 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3096 w = GetSystemMetrics(SM_CXSCREEN);
3097 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3098 h = GetSystemMetrics(SM_CYSCREEN);
3099 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3101 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3102 ddraw1 = create_ddraw();
3103 hr = set_display_mode(ddraw1, 800, 600);
3104 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3105 w = GetSystemMetrics(SM_CXSCREEN);
3106 ok(w == 800, "Got unexpected screen width %u.\n", w);
3107 h = GetSystemMetrics(SM_CYSCREEN);
3108 ok(h == 600, "Got unexpected screen height %u.\n", h);
3110 hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3111 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3113 ddraw2 = create_ddraw();
3114 hr = set_display_mode(ddraw2, 640, 480);
3115 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3117 ref = IDirectDraw_Release(ddraw1);
3118 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3119 w = GetSystemMetrics(SM_CXSCREEN);
3120 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3121 h = GetSystemMetrics(SM_CYSCREEN);
3122 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3124 ref = IDirectDraw_Release(ddraw2);
3125 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3126 w = GetSystemMetrics(SM_CXSCREEN);
3127 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3128 h = GetSystemMetrics(SM_CYSCREEN);
3129 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3131 DestroyWindow(window);
3134 static void test_initialize(void)
3136 IDirectDraw *ddraw;
3137 IDirect3D *d3d;
3138 HRESULT hr;
3140 ddraw = create_ddraw();
3141 ok(!!ddraw, "Failed to create a ddraw object.\n");
3143 hr = IDirectDraw_Initialize(ddraw, NULL);
3144 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3145 IDirectDraw_Release(ddraw);
3147 CoInitialize(NULL);
3148 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw);
3149 ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
3150 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
3151 if (SUCCEEDED(hr))
3153 /* IDirect3D_Initialize() just returns DDERR_ALREADYINITIALIZED. */
3154 hr = IDirect3D_Initialize(d3d, NULL);
3155 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3156 IDirect3D_Release(d3d);
3158 else
3159 skip("D3D interface is not available, skipping test.\n");
3160 hr = IDirectDraw_Initialize(ddraw, NULL);
3161 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3162 hr = IDirectDraw_Initialize(ddraw, NULL);
3163 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3164 IDirectDraw_Release(ddraw);
3165 CoUninitialize();
3167 if (0) /* This crashes on the W2KPROSP4 testbot. */
3169 CoInitialize(NULL);
3170 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d);
3171 ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#x, expected E_NOINTERFACE.\n", hr);
3172 CoUninitialize();
3176 static void test_coop_level_surf_create(void)
3178 IDirectDrawSurface *surface;
3179 IDirectDraw *ddraw;
3180 DDSURFACEDESC ddsd;
3181 HRESULT hr;
3183 ddraw = create_ddraw();
3184 ok(!!ddraw, "Failed to create a ddraw object.\n");
3186 memset(&ddsd, 0, sizeof(ddsd));
3187 ddsd.dwSize = sizeof(ddsd);
3188 ddsd.dwFlags = DDSD_CAPS;
3189 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3190 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3191 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3193 IDirectDraw_Release(ddraw);
3196 static void test_coop_level_multi_window(void)
3198 HWND window1, window2;
3199 IDirectDraw *ddraw;
3200 HRESULT hr;
3202 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3203 0, 0, 640, 480, 0, 0, 0, 0);
3204 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
3205 0, 0, 640, 480, 0, 0, 0, 0);
3206 ddraw = create_ddraw();
3207 ok(!!ddraw, "Failed to create a ddraw object.\n");
3209 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3210 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3211 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3212 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3213 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3214 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3216 IDirectDraw_Release(ddraw);
3217 DestroyWindow(window2);
3218 DestroyWindow(window1);
3221 static void test_clear_rect_count(void)
3223 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3224 IDirect3DMaterial *white, *red, *green, *blue;
3225 IDirect3DViewport *viewport;
3226 IDirect3DDevice *device;
3227 IDirectDrawSurface *rt;
3228 IDirectDraw *ddraw;
3229 D3DCOLOR color;
3230 HWND window;
3231 HRESULT hr;
3233 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3234 0, 0, 640, 480, 0, 0, 0, 0);
3235 ddraw = create_ddraw();
3236 ok(!!ddraw, "Failed to create a ddraw object.\n");
3237 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3239 skip("Failed to create a 3D device, skipping test.\n");
3240 IDirectDraw_Release(ddraw);
3241 DestroyWindow(window);
3242 return;
3245 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
3246 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3248 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
3249 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
3250 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
3251 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
3252 viewport = create_viewport(device, 0, 0, 640, 480);
3254 viewport_set_background(device, viewport, white);
3255 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
3256 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3257 viewport_set_background(device, viewport, red);
3258 hr = IDirect3DViewport_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
3259 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3260 viewport_set_background(device, viewport, green);
3261 hr = IDirect3DViewport_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
3262 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3263 viewport_set_background(device, viewport, blue);
3264 hr = IDirect3DViewport_Clear(viewport, 1, NULL, D3DCLEAR_TARGET);
3265 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3267 color = get_surface_color(rt, 320, 240);
3268 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x000000ff, 1)),
3269 "Got unexpected color 0x%08x.\n", color);
3271 IDirectDrawSurface_Release(rt);
3272 destroy_viewport(device, viewport);
3273 destroy_material(white);
3274 destroy_material(red);
3275 destroy_material(green);
3276 destroy_material(blue);
3277 IDirect3DDevice_Release(device);
3278 IDirectDraw_Release(ddraw);
3279 DestroyWindow(window);
3282 static struct
3284 BOOL received;
3285 IDirectDraw *ddraw;
3286 HWND window;
3287 DWORD coop_level;
3288 } activateapp_testdata;
3290 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3292 if (message == WM_ACTIVATEAPP)
3294 if (activateapp_testdata.ddraw)
3296 HRESULT hr;
3297 activateapp_testdata.received = FALSE;
3298 hr = IDirectDraw_SetCooperativeLevel(activateapp_testdata.ddraw,
3299 activateapp_testdata.window, activateapp_testdata.coop_level);
3300 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
3301 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
3303 activateapp_testdata.received = TRUE;
3306 return DefWindowProcA(hwnd, message, wparam, lparam);
3309 static void test_coop_level_activateapp(void)
3311 IDirectDraw *ddraw;
3312 HRESULT hr;
3313 HWND window;
3314 WNDCLASSA wc = {0};
3315 DDSURFACEDESC ddsd;
3316 IDirectDrawSurface *surface;
3318 ddraw = create_ddraw();
3319 ok(!!ddraw, "Failed to create a ddraw object.\n");
3321 wc.lpfnWndProc = activateapp_test_proc;
3322 wc.lpszClassName = "ddraw_test_wndproc_wc";
3323 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3325 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
3326 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
3328 /* Exclusive with window already active. */
3329 SetForegroundWindow(window);
3330 activateapp_testdata.received = FALSE;
3331 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3332 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3333 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
3334 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3335 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3337 /* Exclusive with window not active. */
3338 SetForegroundWindow(GetDesktopWindow());
3339 activateapp_testdata.received = FALSE;
3340 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3341 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3342 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3343 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3344 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3346 /* Normal with window not active, then exclusive with the same window. */
3347 SetForegroundWindow(GetDesktopWindow());
3348 activateapp_testdata.received = FALSE;
3349 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3350 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3351 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
3352 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3353 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3354 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3355 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3356 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3358 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
3359 SetForegroundWindow(GetDesktopWindow());
3360 activateapp_testdata.received = FALSE;
3361 activateapp_testdata.ddraw = ddraw;
3362 activateapp_testdata.window = window;
3363 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
3364 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3365 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3366 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3367 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3368 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3370 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
3371 * succeeding. Another switch to exclusive and back to normal is needed to release the
3372 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
3373 * WM_ACTIVATEAPP messages. */
3374 activateapp_testdata.ddraw = NULL;
3375 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3376 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3377 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3378 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3380 /* Setting DDSCL_NORMAL with recursive invocation. */
3381 SetForegroundWindow(GetDesktopWindow());
3382 activateapp_testdata.received = FALSE;
3383 activateapp_testdata.ddraw = ddraw;
3384 activateapp_testdata.window = window;
3385 activateapp_testdata.coop_level = DDSCL_NORMAL;
3386 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3387 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3388 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3390 /* DDraw is in exlusive mode now. */
3391 memset(&ddsd, 0, sizeof(ddsd));
3392 ddsd.dwSize = sizeof(ddsd);
3393 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
3394 ddsd.dwBackBufferCount = 1;
3395 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
3396 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3397 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3398 IDirectDrawSurface_Release(surface);
3400 /* Recover again, just to be sure. */
3401 activateapp_testdata.ddraw = NULL;
3402 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3403 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3404 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3405 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3407 DestroyWindow(window);
3408 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3409 IDirectDraw_Release(ddraw);
3412 struct format_support_check
3414 const DDPIXELFORMAT *format;
3415 BOOL supported;
3418 static HRESULT WINAPI test_unsupported_formats_cb(DDSURFACEDESC *desc, void *ctx)
3420 struct format_support_check *format = ctx;
3422 if (!memcmp(format->format, &desc->ddpfPixelFormat, sizeof(*format->format)))
3424 format->supported = TRUE;
3425 return DDENUMRET_CANCEL;
3428 return DDENUMRET_OK;
3431 static void test_unsupported_formats(void)
3433 HRESULT hr;
3434 BOOL expect_success;
3435 HWND window;
3436 IDirectDraw *ddraw;
3437 IDirect3DDevice *device;
3438 IDirectDrawSurface *surface;
3439 DDSURFACEDESC ddsd;
3440 unsigned int i, j;
3441 DWORD expected_caps;
3442 static const struct
3444 const char *name;
3445 DDPIXELFORMAT fmt;
3447 formats[] =
3450 "D3DFMT_A8R8G8B8",
3452 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3453 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
3457 "D3DFMT_P8",
3459 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3460 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3464 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
3466 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3467 0, 0, 640, 480, 0, 0, 0, 0);
3468 ddraw = create_ddraw();
3469 ok(!!ddraw, "Failed to create a ddraw object.\n");
3470 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3472 skip("Failed to create a 3D device, skipping test.\n");
3473 IDirectDraw_Release(ddraw);
3474 DestroyWindow(window);
3475 return;
3478 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
3480 struct format_support_check check = {&formats[i].fmt, FALSE};
3481 hr = IDirect3DDevice_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
3482 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
3484 for (j = 0; j < sizeof(caps) / sizeof(*caps); j++)
3486 memset(&ddsd, 0, sizeof(ddsd));
3487 ddsd.dwSize = sizeof(ddsd);
3488 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3489 ddsd.ddpfPixelFormat = formats[i].fmt;
3490 ddsd.dwWidth = 4;
3491 ddsd.dwHeight = 4;
3492 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
3494 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
3495 expect_success = FALSE;
3496 else
3497 expect_success = TRUE;
3499 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3500 ok(SUCCEEDED(hr) == expect_success,
3501 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
3502 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
3503 if (FAILED(hr))
3504 continue;
3506 memset(&ddsd, 0, sizeof(ddsd));
3507 ddsd.dwSize = sizeof(ddsd);
3508 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
3509 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3511 if (caps[j] & DDSCAPS_VIDEOMEMORY)
3512 expected_caps = DDSCAPS_VIDEOMEMORY;
3513 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
3514 expected_caps = DDSCAPS_SYSTEMMEMORY;
3515 else if (check.supported)
3516 expected_caps = DDSCAPS_VIDEOMEMORY;
3517 else
3518 expected_caps = DDSCAPS_SYSTEMMEMORY;
3520 ok(ddsd.ddsCaps.dwCaps & expected_caps,
3521 "Expected capability %#x, format %s, input cap %#x.\n",
3522 expected_caps, formats[i].name, caps[j]);
3524 IDirectDrawSurface_Release(surface);
3528 IDirect3DDevice_Release(device);
3529 IDirectDraw_Release(ddraw);
3530 DestroyWindow(window);
3533 static void test_rt_caps(void)
3535 PALETTEENTRY palette_entries[256];
3536 IDirectDrawPalette *palette;
3537 IDirect3DDevice *device;
3538 IDirectDraw *ddraw;
3539 DWORD z_depth = 0;
3540 unsigned int i;
3541 ULONG refcount;
3542 HWND window;
3543 HRESULT hr;
3545 static const DDPIXELFORMAT p8_fmt =
3547 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3548 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
3551 static const struct
3553 const DDPIXELFORMAT *pf;
3554 DWORD caps_in;
3555 DWORD caps_out;
3556 HRESULT create_device_hr;
3557 BOOL create_may_fail;
3559 test_data[] =
3562 NULL,
3563 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3564 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3565 D3D_OK,
3566 FALSE,
3569 NULL,
3570 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3571 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3572 D3D_OK,
3573 FALSE,
3576 NULL,
3577 DDSCAPS_OFFSCREENPLAIN,
3578 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3579 DDERR_INVALIDCAPS,
3580 FALSE,
3583 NULL,
3584 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3585 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3586 D3DERR_SURFACENOTINVIDMEM,
3587 FALSE,
3590 NULL,
3591 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3592 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3593 DDERR_INVALIDCAPS,
3594 FALSE,
3597 NULL,
3598 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3599 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3600 D3D_OK,
3601 FALSE,
3604 NULL,
3605 DDSCAPS_3DDEVICE,
3606 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3607 D3D_OK,
3608 FALSE,
3611 NULL,
3613 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3614 DDERR_INVALIDCAPS,
3615 FALSE,
3618 NULL,
3619 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3620 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3621 D3DERR_SURFACENOTINVIDMEM,
3622 FALSE,
3625 NULL,
3626 DDSCAPS_SYSTEMMEMORY,
3627 DDSCAPS_SYSTEMMEMORY,
3628 DDERR_INVALIDCAPS,
3629 FALSE,
3632 &p8_fmt,
3634 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3635 DDERR_INVALIDCAPS,
3636 FALSE,
3639 &p8_fmt,
3640 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3641 ~0U /* AMD r200 */ ,
3642 DDERR_NOPALETTEATTACHED,
3643 FALSE,
3646 &p8_fmt,
3647 DDSCAPS_OFFSCREENPLAIN,
3648 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3649 DDERR_INVALIDCAPS,
3650 FALSE,
3653 &p8_fmt,
3654 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3655 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3656 DDERR_NOPALETTEATTACHED,
3657 FALSE,
3660 &p8_fmt,
3661 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3662 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3663 DDERR_INVALIDCAPS,
3664 FALSE,
3667 NULL,
3668 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
3669 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
3670 DDERR_INVALIDCAPS,
3671 TRUE /* AMD Evergreen */,
3674 NULL,
3675 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3676 ~0U /* AMD Evergreen */,
3677 DDERR_INVALIDCAPS,
3678 FALSE,
3681 NULL,
3682 DDSCAPS_ZBUFFER,
3683 ~0U /* AMD Evergreen */,
3684 DDERR_INVALIDCAPS,
3685 FALSE,
3688 NULL,
3689 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3690 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3691 DDERR_INVALIDCAPS,
3692 TRUE /* Nvidia Kepler */,
3695 NULL,
3696 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3697 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3698 DDERR_INVALIDCAPS,
3699 TRUE /* Nvidia Kepler */,
3703 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3704 0, 0, 640, 480, 0, 0, 0, 0);
3705 ddraw = create_ddraw();
3706 ok(!!ddraw, "Failed to create a ddraw object.\n");
3707 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3709 skip("Failed to create a 3D device, skipping test.\n");
3710 IDirectDraw_Release(ddraw);
3711 DestroyWindow(window);
3712 return;
3714 z_depth = get_device_z_depth(device);
3715 ok(!!z_depth, "Failed to get device z depth.\n");
3716 IDirect3DDevice_Release(device);
3718 memset(palette_entries, 0, sizeof(palette_entries));
3719 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
3720 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
3722 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
3724 IDirectDrawSurface *surface;
3725 DDSURFACEDESC surface_desc;
3726 IDirect3DDevice *device;
3728 memset(&surface_desc, 0, sizeof(surface_desc));
3729 surface_desc.dwSize = sizeof(surface_desc);
3730 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3731 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
3732 if (test_data[i].pf)
3734 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
3735 surface_desc.ddpfPixelFormat = *test_data[i].pf;
3737 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
3739 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
3740 U2(surface_desc).dwZBufferBitDepth = z_depth;
3742 surface_desc.dwWidth = 640;
3743 surface_desc.dwHeight = 480;
3744 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3745 ok(SUCCEEDED(hr) || broken(test_data[i].create_may_fail),
3746 "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
3747 i, test_data[i].caps_in, hr);
3748 if (FAILED(hr))
3749 continue;
3751 memset(&surface_desc, 0, sizeof(surface_desc));
3752 surface_desc.dwSize = sizeof(surface_desc);
3753 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
3754 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
3755 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
3756 "Test %u: Got unexpected caps %#x, expected %#x.\n",
3757 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
3759 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
3760 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
3761 i, hr, test_data[i].create_device_hr);
3762 if (hr == DDERR_NOPALETTEATTACHED)
3764 hr = IDirectDrawSurface_SetPalette(surface, palette);
3765 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
3766 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
3767 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
3768 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
3769 else
3770 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
3772 if (SUCCEEDED(hr))
3774 refcount = IDirect3DDevice_Release(device);
3775 ok(refcount == 1, "Test %u: Got unexpected refcount %u.\n", i, refcount);
3778 refcount = IDirectDrawSurface_Release(surface);
3779 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
3782 IDirectDrawPalette_Release(palette);
3783 refcount = IDirectDraw_Release(ddraw);
3784 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3785 DestroyWindow(window);
3788 static void test_primary_caps(void)
3790 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
3791 IDirectDrawSurface *surface;
3792 DDSURFACEDESC surface_desc;
3793 IDirectDraw *ddraw;
3794 unsigned int i;
3795 ULONG refcount;
3796 HWND window;
3797 HRESULT hr;
3799 static const struct
3801 DWORD coop_level;
3802 DWORD caps_in;
3803 DWORD back_buffer_count;
3804 HRESULT hr;
3805 DWORD caps_out;
3807 test_data[] =
3810 DDSCL_NORMAL,
3811 DDSCAPS_PRIMARYSURFACE,
3812 ~0u,
3813 DD_OK,
3814 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
3817 DDSCL_NORMAL,
3818 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
3819 ~0u,
3820 DDERR_INVALIDCAPS,
3821 ~0u,
3824 DDSCL_NORMAL,
3825 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
3826 ~0u,
3827 DD_OK,
3828 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
3831 DDSCL_NORMAL,
3832 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
3833 ~0u,
3834 DDERR_INVALIDCAPS,
3835 ~0u,
3838 DDSCL_NORMAL,
3839 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
3840 ~0u,
3841 DDERR_INVALIDCAPS,
3842 ~0u,
3845 DDSCL_NORMAL,
3846 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
3847 ~0u,
3848 DDERR_INVALIDCAPS,
3849 ~0u,
3852 DDSCL_NORMAL,
3853 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3854 ~0u,
3855 DDERR_INVALIDCAPS,
3856 ~0u,
3859 DDSCL_NORMAL,
3860 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3862 DDERR_INVALIDCAPS,
3863 ~0u,
3866 DDSCL_NORMAL,
3867 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3869 DDERR_NOEXCLUSIVEMODE,
3870 ~0u,
3873 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3874 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3876 DDERR_INVALIDCAPS,
3877 ~0u,
3880 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3881 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3883 DD_OK,
3884 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
3887 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3888 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
3890 DDERR_INVALIDCAPS,
3891 ~0u,
3894 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3895 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
3897 DDERR_INVALIDCAPS,
3898 ~0u,
3902 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3903 0, 0, 640, 480, 0, 0, 0, 0);
3904 ddraw = create_ddraw();
3905 ok(!!ddraw, "Failed to create a ddraw object.\n");
3907 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
3909 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
3910 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3912 memset(&surface_desc, 0, sizeof(surface_desc));
3913 surface_desc.dwSize = sizeof(surface_desc);
3914 surface_desc.dwFlags = DDSD_CAPS;
3915 if (test_data[i].back_buffer_count != ~0u)
3916 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
3917 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
3918 surface_desc.dwBackBufferCount = test_data[i].back_buffer_count;
3919 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3920 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
3921 if (FAILED(hr))
3922 continue;
3924 memset(&surface_desc, 0, sizeof(surface_desc));
3925 surface_desc.dwSize = sizeof(surface_desc);
3926 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
3927 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
3928 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
3929 "Test %u: Got unexpected caps %#x, expected %#x.\n",
3930 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
3932 IDirectDrawSurface_Release(surface);
3935 refcount = IDirectDraw_Release(ddraw);
3936 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3937 DestroyWindow(window);
3940 static void test_surface_lock(void)
3942 IDirectDraw *ddraw;
3943 IDirectDrawSurface *surface;
3944 IDirect3DDevice *device;
3945 HRESULT hr;
3946 HWND window;
3947 unsigned int i;
3948 DDSURFACEDESC ddsd;
3949 ULONG refcount;
3950 DWORD z_depth = 0;
3951 static const struct
3953 DWORD caps;
3954 const char *name;
3956 tests[] =
3959 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
3960 "videomemory offscreenplain"
3963 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3964 "systemmemory offscreenplain"
3967 DDSCAPS_PRIMARYSURFACE,
3968 "primary"
3971 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
3972 "videomemory texture"
3975 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
3976 "systemmemory texture"
3979 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3980 "render target"
3983 DDSCAPS_ZBUFFER,
3984 "Z buffer"
3988 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3989 0, 0, 640, 480, 0, 0, 0, 0);
3990 ddraw = create_ddraw();
3991 ok(!!ddraw, "Failed to create a ddraw object.\n");
3992 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3994 skip("Failed to create a 3D device, skipping test.\n");
3995 IDirectDraw_Release(ddraw);
3996 DestroyWindow(window);
3997 return;
3999 z_depth = get_device_z_depth(device);
4000 ok(!!z_depth, "Failed to get device z depth.\n");
4001 IDirect3DDevice_Release(device);
4003 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4005 memset(&ddsd, 0, sizeof(ddsd));
4006 ddsd.dwSize = sizeof(ddsd);
4007 ddsd.dwFlags = DDSD_CAPS;
4008 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
4010 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
4011 ddsd.dwWidth = 64;
4012 ddsd.dwHeight = 64;
4014 if (tests[i].caps & DDSCAPS_ZBUFFER)
4016 ddsd.dwFlags |= DDSD_ZBUFFERBITDEPTH;
4017 U2(ddsd).dwZBufferBitDepth = z_depth;
4019 ddsd.ddsCaps.dwCaps = tests[i].caps;
4021 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4022 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
4024 memset(&ddsd, 0, sizeof(ddsd));
4025 ddsd.dwSize = sizeof(ddsd);
4026 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
4027 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
4028 if (SUCCEEDED(hr))
4030 hr = IDirectDrawSurface_Unlock(surface, NULL);
4031 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
4034 IDirectDrawSurface_Release(surface);
4037 refcount = IDirectDraw_Release(ddraw);
4038 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4039 DestroyWindow(window);
4042 static void test_surface_discard(void)
4044 IDirectDraw *ddraw;
4045 IDirect3DDevice *device;
4046 HRESULT hr;
4047 HWND window;
4048 DDSURFACEDESC ddsd;
4049 IDirectDrawSurface *surface, *target;
4050 void *addr;
4051 static const struct
4053 DWORD caps;
4054 BOOL discard;
4056 tests[] =
4058 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, TRUE},
4059 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, FALSE},
4060 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, TRUE},
4061 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, FALSE},
4063 unsigned int i;
4065 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4066 0, 0, 640, 480, 0, 0, 0, 0);
4067 ddraw = create_ddraw();
4068 ok(!!ddraw, "Failed to create a ddraw object.\n");
4069 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4071 skip("Failed to create a 3D device, skipping test.\n");
4072 IDirectDraw_Release(ddraw);
4073 DestroyWindow(window);
4074 return;
4077 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&target);
4078 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4080 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4082 BOOL discarded;
4084 memset(&ddsd, 0, sizeof(ddsd));
4085 ddsd.dwSize = sizeof(ddsd);
4086 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4087 ddsd.ddsCaps.dwCaps = tests[i].caps;
4088 ddsd.dwWidth = 64;
4089 ddsd.dwHeight = 64;
4090 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4091 if (FAILED(hr))
4093 skip("Failed to create surface, skipping.\n");
4094 continue;
4097 memset(&ddsd, 0, sizeof(ddsd));
4098 ddsd.dwSize = sizeof(ddsd);
4099 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
4100 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4101 addr = ddsd.lpSurface;
4102 hr = IDirectDrawSurface_Unlock(surface, NULL);
4103 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4105 memset(&ddsd, 0, sizeof(ddsd));
4106 ddsd.dwSize = sizeof(ddsd);
4107 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
4108 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4109 discarded = ddsd.lpSurface != addr;
4110 hr = IDirectDrawSurface_Unlock(surface, NULL);
4111 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4113 hr = IDirectDrawSurface_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
4114 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
4116 memset(&ddsd, 0, sizeof(ddsd));
4117 ddsd.dwSize = sizeof(ddsd);
4118 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
4119 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4120 discarded |= ddsd.lpSurface != addr;
4121 hr = IDirectDrawSurface_Unlock(surface, NULL);
4122 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4124 IDirectDrawSurface_Release(surface);
4126 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
4127 * AMD r500, evergreen). Windows XP, at least on AMD r200, never changes the pointer. */
4128 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
4131 IDirectDrawSurface_Release(target);
4132 IDirect3DDevice_Release(device);
4133 IDirectDraw_Release(ddraw);
4134 DestroyWindow(window);
4137 static void test_flip(void)
4139 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
4140 IDirectDrawSurface *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
4141 DDSCAPS caps = {DDSCAPS_FLIP};
4142 DDSURFACEDESC surface_desc;
4143 BOOL sysmem_primary;
4144 IDirectDraw *ddraw;
4145 DWORD expected_caps;
4146 unsigned int i;
4147 D3DCOLOR color;
4148 ULONG refcount;
4149 HWND window;
4150 DDBLTFX fx;
4151 HRESULT hr;
4153 static const struct
4155 const char *name;
4156 DWORD caps;
4158 test_data[] =
4160 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
4161 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
4162 {"TEXTURE", DDSCAPS_TEXTURE},
4165 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4166 0, 0, 640, 480, 0, 0, 0, 0);
4167 ddraw = create_ddraw();
4168 ok(!!ddraw, "Failed to create a ddraw object.\n");
4170 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4171 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4173 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
4175 memset(&surface_desc, 0, sizeof(surface_desc));
4176 surface_desc.dwSize = sizeof(surface_desc);
4177 surface_desc.dwFlags = DDSD_CAPS;
4178 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
4179 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
4180 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
4181 surface_desc.dwWidth = 512;
4182 surface_desc.dwHeight = 512;
4183 surface_desc.dwBackBufferCount = 3;
4184 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
4185 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4187 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
4188 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
4189 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
4190 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4192 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
4193 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
4194 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
4195 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4197 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
4198 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
4199 todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
4200 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
4201 if (FAILED(hr))
4202 continue;
4204 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
4205 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
4206 hr = IDirectDrawSurface_IsLost(frontbuffer);
4207 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4208 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
4209 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
4210 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4211 else
4212 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4213 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4214 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
4215 hr = IDirectDrawSurface_IsLost(frontbuffer);
4216 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4217 hr = restore_surfaces(ddraw);
4218 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
4220 memset(&surface_desc, 0, sizeof(surface_desc));
4221 surface_desc.dwSize = sizeof(surface_desc);
4222 hr = IDirectDrawSurface_GetSurfaceDesc(frontbuffer, &surface_desc);
4223 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
4224 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
4225 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
4226 expected_caps |= DDSCAPS_VISIBLE;
4227 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
4228 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
4229 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
4231 hr = IDirectDrawSurface_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
4232 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
4233 memset(&surface_desc, 0, sizeof(surface_desc));
4234 surface_desc.dwSize = sizeof(surface_desc);
4235 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer1, &surface_desc);
4236 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
4237 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
4238 test_data[i].name, surface_desc.dwBackBufferCount);
4239 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
4240 expected_caps |= DDSCAPS_BACKBUFFER;
4241 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
4242 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
4244 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
4245 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
4246 memset(&surface_desc, 0, sizeof(surface_desc));
4247 surface_desc.dwSize = sizeof(surface_desc);
4248 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer2, &surface_desc);
4249 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
4250 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
4251 test_data[i].name, surface_desc.dwBackBufferCount);
4252 expected_caps &= ~DDSCAPS_BACKBUFFER;
4253 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
4254 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
4256 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
4257 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
4258 memset(&surface_desc, 0, sizeof(surface_desc));
4259 surface_desc.dwSize = sizeof(surface_desc);
4260 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer3, &surface_desc);
4261 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
4262 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
4263 test_data[i].name, surface_desc.dwBackBufferCount);
4264 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
4265 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
4267 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer3, &caps, &surface);
4268 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
4269 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
4270 test_data[i].name, surface, frontbuffer);
4271 IDirectDrawSurface_Release(surface);
4273 memset(&surface_desc, 0, sizeof(surface_desc));
4274 surface_desc.dwSize = sizeof(surface_desc);
4275 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4276 surface_desc.ddsCaps.dwCaps = 0;
4277 surface_desc.dwWidth = 640;
4278 surface_desc.dwHeight = 480;
4279 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4280 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
4281 hr = IDirectDrawSurface_Flip(frontbuffer, surface, DDFLIP_WAIT);
4282 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4283 IDirectDrawSurface_Release(surface);
4285 hr = IDirectDrawSurface_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
4286 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4287 hr = IDirectDrawSurface_Flip(backbuffer1, NULL, DDFLIP_WAIT);
4288 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4289 hr = IDirectDrawSurface_Flip(backbuffer2, NULL, DDFLIP_WAIT);
4290 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4291 hr = IDirectDrawSurface_Flip(backbuffer3, NULL, DDFLIP_WAIT);
4292 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
4294 memset(&fx, 0, sizeof(fx));
4295 fx.dwSize = sizeof(fx);
4296 U5(fx).dwFillColor = 0xffff0000;
4297 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4298 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4299 U5(fx).dwFillColor = 0xff00ff00;
4300 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4301 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4302 U5(fx).dwFillColor = 0xff0000ff;
4303 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4304 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4306 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
4307 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4308 color = get_surface_color(backbuffer1, 320, 240);
4309 /* The testbot seems to just copy the contents of one surface to all the
4310 * others, instead of properly flipping. */
4311 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
4312 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4313 color = get_surface_color(backbuffer2, 320, 240);
4314 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4315 U5(fx).dwFillColor = 0xffff0000;
4316 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4317 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4319 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
4320 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4321 color = get_surface_color(backbuffer1, 320, 240);
4322 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
4323 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4324 color = get_surface_color(backbuffer2, 320, 240);
4325 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4326 U5(fx).dwFillColor = 0xff00ff00;
4327 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4328 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4330 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
4331 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4332 color = get_surface_color(backbuffer1, 320, 240);
4333 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
4334 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4335 color = get_surface_color(backbuffer2, 320, 240);
4336 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4337 U5(fx).dwFillColor = 0xff0000ff;
4338 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4339 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4341 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
4342 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4343 color = get_surface_color(backbuffer2, 320, 240);
4344 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
4345 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4346 color = get_surface_color(backbuffer3, 320, 240);
4347 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4348 U5(fx).dwFillColor = 0xffff0000;
4349 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4350 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4352 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
4353 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4354 color = get_surface_color(backbuffer1, 320, 240);
4355 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4356 color = get_surface_color(backbuffer3, 320, 240);
4357 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
4358 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4359 U5(fx).dwFillColor = 0xff00ff00;
4360 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4361 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
4363 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
4364 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
4365 color = get_surface_color(backbuffer1, 320, 240);
4366 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
4367 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4368 color = get_surface_color(backbuffer2, 320, 240);
4369 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
4371 IDirectDrawSurface_Release(backbuffer3);
4372 IDirectDrawSurface_Release(backbuffer2);
4373 IDirectDrawSurface_Release(backbuffer1);
4374 IDirectDrawSurface_Release(frontbuffer);
4377 refcount = IDirectDraw_Release(ddraw);
4378 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4379 DestroyWindow(window);
4382 static void test_sysmem_overlay(void)
4384 IDirectDraw *ddraw;
4385 HWND window;
4386 HRESULT hr;
4387 DDSURFACEDESC ddsd;
4388 IDirectDrawSurface *surface;
4389 ULONG ref;
4391 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4392 0, 0, 640, 480, 0, 0, 0, 0);
4393 ddraw = create_ddraw();
4394 ok(!!ddraw, "Failed to create a ddraw object.\n");
4396 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4397 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4399 memset(&ddsd, 0, sizeof(ddsd));
4400 ddsd.dwSize = sizeof(ddsd);
4401 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
4402 ddsd.dwWidth = 16;
4403 ddsd.dwHeight = 16;
4404 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
4405 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4406 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4407 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4408 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4409 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4410 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4411 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4412 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
4414 ref = IDirectDraw_Release(ddraw);
4415 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
4416 DestroyWindow(window);
4419 static void test_primary_palette(void)
4421 DDSCAPS surface_caps = {DDSCAPS_FLIP};
4422 IDirectDrawSurface *primary, *backbuffer;
4423 PALETTEENTRY palette_entries[256];
4424 IDirectDrawPalette *palette, *tmp;
4425 DDSURFACEDESC surface_desc;
4426 IDirectDraw *ddraw;
4427 DWORD palette_caps;
4428 ULONG refcount;
4429 HWND window;
4430 HRESULT hr;
4432 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4433 0, 0, 640, 480, 0, 0, 0, 0);
4434 ddraw = create_ddraw();
4435 ok(!!ddraw, "Failed to create a ddraw object.\n");
4436 if (FAILED(IDirectDraw_SetDisplayMode(ddraw, 640, 480, 8)))
4438 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
4439 IDirectDraw_Release(ddraw);
4440 DestroyWindow(window);
4441 return;
4443 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4444 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4446 memset(&surface_desc, 0, sizeof(surface_desc));
4447 surface_desc.dwSize = sizeof(surface_desc);
4448 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4449 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4450 surface_desc.dwBackBufferCount = 1;
4451 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
4452 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4453 hr = IDirectDrawSurface_GetAttachedSurface(primary, &surface_caps, &backbuffer);
4454 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4456 memset(palette_entries, 0, sizeof(palette_entries));
4457 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
4458 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
4459 refcount = get_refcount((IUnknown *)palette);
4460 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4462 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
4463 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
4464 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
4466 hr = IDirectDrawSurface_SetPalette(primary, palette);
4467 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
4469 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
4470 * and is generally somewhat broken with respect to 8 bpp / palette
4471 * handling. */
4472 if (SUCCEEDED(IDirectDrawSurface_GetPalette(backbuffer, &tmp)))
4474 win_skip("Broken palette handling detected, skipping tests.\n");
4475 IDirectDrawPalette_Release(tmp);
4476 IDirectDrawPalette_Release(palette);
4477 /* The Windows 8 testbot keeps extra references to the primary and
4478 * backbuffer while in 8 bpp mode. */
4479 hr = IDirectDraw_RestoreDisplayMode(ddraw);
4480 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
4481 goto done;
4484 refcount = get_refcount((IUnknown *)palette);
4485 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4487 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
4488 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
4489 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
4490 "Got unexpected palette caps %#x.\n", palette_caps);
4492 hr = IDirectDrawSurface_SetPalette(primary, NULL);
4493 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
4494 refcount = get_refcount((IUnknown *)palette);
4495 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4497 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
4498 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
4499 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
4501 hr = IDirectDrawSurface_SetPalette(primary, palette);
4502 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
4503 refcount = get_refcount((IUnknown *)palette);
4504 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4506 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
4507 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
4508 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
4509 IDirectDrawPalette_Release(tmp);
4510 hr = IDirectDrawSurface_GetPalette(backbuffer, &tmp);
4511 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
4513 refcount = IDirectDrawPalette_Release(palette);
4514 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4515 refcount = IDirectDrawPalette_Release(palette);
4516 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4518 /* Note that this only seems to work when the palette is attached to the
4519 * primary surface. When attached to a regular surface, attempting to get
4520 * the palette here will cause an access violation. */
4521 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
4522 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
4524 done:
4525 refcount = IDirectDrawSurface_Release(backbuffer);
4526 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4527 refcount = IDirectDrawSurface_Release(primary);
4528 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4529 refcount = IDirectDraw_Release(ddraw);
4530 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4531 DestroyWindow(window);
4534 static HRESULT WINAPI surface_counter(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
4536 UINT *surface_count = context;
4538 ++(*surface_count);
4539 IDirectDrawSurface_Release(surface);
4541 return DDENUMRET_OK;
4544 static void test_surface_attachment(void)
4546 IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
4547 DDSCAPS caps = {DDSCAPS_TEXTURE};
4548 DDSURFACEDESC surface_desc;
4549 IDirectDraw *ddraw;
4550 UINT surface_count;
4551 ULONG refcount;
4552 HWND window;
4553 HRESULT hr;
4555 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4556 0, 0, 640, 480, 0, 0, 0, 0);
4557 ddraw = create_ddraw();
4558 ok(!!ddraw, "Failed to create a ddraw object.\n");
4559 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4560 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4562 memset(&surface_desc, 0, sizeof(surface_desc));
4563 surface_desc.dwSize = sizeof(surface_desc);
4564 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
4565 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
4566 U2(surface_desc).dwMipMapCount = 3;
4567 surface_desc.dwWidth = 128;
4568 surface_desc.dwHeight = 128;
4569 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4570 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4572 hr = IDirectDrawSurface_GetAttachedSurface(surface1, &caps, &surface2);
4573 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
4574 hr = IDirectDrawSurface_GetAttachedSurface(surface2, &caps, &surface3);
4575 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
4576 hr = IDirectDrawSurface_GetAttachedSurface(surface3, &caps, &surface4);
4577 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
4579 surface_count = 0;
4580 IDirectDrawSurface_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
4581 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
4582 surface_count = 0;
4583 IDirectDrawSurface_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
4584 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
4585 surface_count = 0;
4586 IDirectDrawSurface_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
4587 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
4589 memset(&surface_desc, 0, sizeof(surface_desc));
4590 surface_desc.dwSize = sizeof(surface_desc);
4591 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4592 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
4593 surface_desc.dwWidth = 16;
4594 surface_desc.dwHeight = 16;
4595 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4596 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4598 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
4599 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4600 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4601 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4602 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
4603 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4604 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
4605 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4606 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
4607 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4608 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
4609 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4611 IDirectDrawSurface_Release(surface4);
4613 memset(&surface_desc, 0, sizeof(surface_desc));
4614 surface_desc.dwSize = sizeof(surface_desc);
4615 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4616 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
4617 surface_desc.dwWidth = 16;
4618 surface_desc.dwHeight = 16;
4619 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4620 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4622 if (SUCCEEDED(hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4)))
4624 skip("Running on refrast, skipping some tests.\n");
4625 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface4);
4626 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4628 else
4630 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4631 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4632 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4633 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
4634 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4635 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
4636 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4637 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
4638 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4639 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
4640 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4643 IDirectDrawSurface_Release(surface4);
4644 IDirectDrawSurface_Release(surface3);
4645 IDirectDrawSurface_Release(surface2);
4646 IDirectDrawSurface_Release(surface1);
4648 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4649 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4651 /* Try a single primary and two offscreen plain surfaces. */
4652 memset(&surface_desc, 0, sizeof(surface_desc));
4653 surface_desc.dwSize = sizeof(surface_desc);
4654 surface_desc.dwFlags = DDSD_CAPS;
4655 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4656 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4657 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4659 memset(&surface_desc, 0, sizeof(surface_desc));
4660 surface_desc.dwSize = sizeof(surface_desc);
4661 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4662 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4663 surface_desc.dwWidth = registry_mode.dmPelsWidth;
4664 surface_desc.dwHeight = registry_mode.dmPelsHeight;
4665 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
4666 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4668 memset(&surface_desc, 0, sizeof(surface_desc));
4669 surface_desc.dwSize = sizeof(surface_desc);
4670 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4671 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4672 surface_desc.dwWidth = registry_mode.dmPelsWidth;
4673 surface_desc.dwHeight = registry_mode.dmPelsHeight;
4674 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
4675 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4677 /* This one has a different size. */
4678 memset(&surface_desc, 0, sizeof(surface_desc));
4679 surface_desc.dwSize = sizeof(surface_desc);
4680 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4681 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4682 surface_desc.dwWidth = 128;
4683 surface_desc.dwHeight = 128;
4684 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4685 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4687 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4688 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4689 /* Try the reverse without detaching first. */
4690 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
4691 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
4692 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4693 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4695 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
4696 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4697 /* Try to detach reversed. */
4698 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4699 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
4700 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
4701 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4703 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
4704 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4705 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
4706 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4708 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
4709 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4710 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4711 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4713 IDirectDrawSurface_Release(surface4);
4714 IDirectDrawSurface_Release(surface3);
4715 IDirectDrawSurface_Release(surface2);
4716 IDirectDrawSurface_Release(surface1);
4718 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
4719 memset(&surface_desc, 0, sizeof(surface_desc));
4720 surface_desc.dwSize = sizeof(surface_desc);
4721 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4722 surface_desc.dwWidth = 64;
4723 surface_desc.dwHeight = 64;
4724 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4725 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
4726 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
4727 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
4728 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
4729 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
4730 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
4731 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4732 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4733 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
4734 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4736 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4737 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
4738 U1(surface_desc.ddpfPixelFormat).dwZBufferBitDepth = 16;
4739 U3(surface_desc.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
4740 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
4741 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4743 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4744 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4745 refcount = get_refcount((IUnknown *)surface2);
4746 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4747 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4748 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
4750 /* Attaching while already attached to other surface. */
4751 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
4752 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4753 hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
4754 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4755 IDirectDrawSurface_Release(surface3);
4757 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4758 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4759 refcount = get_refcount((IUnknown *)surface2);
4760 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4762 /* Automatic detachment on release. */
4763 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4764 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4765 refcount = get_refcount((IUnknown *)surface2);
4766 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4767 refcount = IDirectDrawSurface_Release(surface1);
4768 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4769 refcount = IDirectDrawSurface_Release(surface2);
4770 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4771 refcount = IDirectDraw_Release(ddraw);
4772 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4773 DestroyWindow(window);
4776 static void test_pixel_format(void)
4778 HWND window, window2 = NULL;
4779 HDC hdc, hdc2 = NULL;
4780 HMODULE gl = NULL;
4781 int format, test_format;
4782 PIXELFORMATDESCRIPTOR pfd;
4783 IDirectDraw *ddraw = NULL;
4784 IDirectDrawClipper *clipper = NULL;
4785 DDSURFACEDESC ddsd;
4786 IDirectDrawSurface *primary = NULL;
4787 DDBLTFX fx;
4788 HRESULT hr;
4790 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4791 100, 100, 160, 160, NULL, NULL, NULL, NULL);
4792 if (!window)
4794 skip("Failed to create window\n");
4795 return;
4798 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4799 100, 100, 160, 160, NULL, NULL, NULL, NULL);
4801 hdc = GetDC(window);
4802 if (!hdc)
4804 skip("Failed to get DC\n");
4805 goto cleanup;
4808 if (window2)
4809 hdc2 = GetDC(window2);
4811 gl = LoadLibraryA("opengl32.dll");
4812 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
4814 format = GetPixelFormat(hdc);
4815 ok(format == 0, "new window has pixel format %d\n", format);
4817 ZeroMemory(&pfd, sizeof(pfd));
4818 pfd.nSize = sizeof(pfd);
4819 pfd.nVersion = 1;
4820 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
4821 pfd.iPixelType = PFD_TYPE_RGBA;
4822 pfd.iLayerType = PFD_MAIN_PLANE;
4823 format = ChoosePixelFormat(hdc, &pfd);
4824 if (format <= 0)
4826 skip("no pixel format available\n");
4827 goto cleanup;
4830 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
4832 skip("failed to set pixel format\n");
4833 goto cleanup;
4836 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
4838 skip("failed to set pixel format on second window\n");
4839 if (hdc2)
4841 ReleaseDC(window2, hdc2);
4842 hdc2 = NULL;
4846 ddraw = create_ddraw();
4847 ok(!!ddraw, "Failed to create a ddraw object.\n");
4849 test_format = GetPixelFormat(hdc);
4850 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4852 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4853 if (FAILED(hr))
4855 skip("Failed to set cooperative level, hr %#x.\n", hr);
4856 goto cleanup;
4859 test_format = GetPixelFormat(hdc);
4860 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4862 if (hdc2)
4864 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
4865 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
4866 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
4867 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
4869 test_format = GetPixelFormat(hdc);
4870 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4872 test_format = GetPixelFormat(hdc2);
4873 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4876 memset(&ddsd, 0, sizeof(ddsd));
4877 ddsd.dwSize = sizeof(ddsd);
4878 ddsd.dwFlags = DDSD_CAPS;
4879 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4881 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
4882 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4884 test_format = GetPixelFormat(hdc);
4885 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4887 if (hdc2)
4889 test_format = GetPixelFormat(hdc2);
4890 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4893 if (clipper)
4895 hr = IDirectDrawSurface_SetClipper(primary, clipper);
4896 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
4898 test_format = GetPixelFormat(hdc);
4899 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4901 test_format = GetPixelFormat(hdc2);
4902 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4905 memset(&fx, 0, sizeof(fx));
4906 fx.dwSize = sizeof(fx);
4907 hr = IDirectDrawSurface_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4908 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
4910 test_format = GetPixelFormat(hdc);
4911 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4913 if (hdc2)
4915 test_format = GetPixelFormat(hdc2);
4916 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4919 cleanup:
4920 if (primary) IDirectDrawSurface_Release(primary);
4921 if (clipper) IDirectDrawClipper_Release(clipper);
4922 if (ddraw) IDirectDraw_Release(ddraw);
4923 if (gl) FreeLibrary(gl);
4924 if (hdc) ReleaseDC(window, hdc);
4925 if (hdc2) ReleaseDC(window2, hdc2);
4926 if (window) DestroyWindow(window);
4927 if (window2) DestroyWindow(window2);
4930 static void test_create_surface_pitch(void)
4932 IDirectDrawSurface *surface;
4933 DDSURFACEDESC surface_desc;
4934 IDirectDraw *ddraw;
4935 unsigned int i;
4936 ULONG refcount;
4937 HWND window;
4938 HRESULT hr;
4939 void *mem;
4941 static const struct
4943 DWORD caps;
4944 DWORD flags_in;
4945 DWORD pitch_in;
4946 HRESULT hr;
4947 DWORD flags_out;
4948 DWORD pitch_out32;
4949 DWORD pitch_out64;
4951 test_data[] =
4953 /* 0 */
4954 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
4955 0, 0, DD_OK,
4956 DDSD_PITCH, 0x100, 0x100},
4957 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
4958 DDSD_PITCH, 0x104, DD_OK,
4959 DDSD_PITCH, 0x100, 0x100},
4960 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
4961 DDSD_PITCH, 0x0f8, DD_OK,
4962 DDSD_PITCH, 0x100, 0x100},
4963 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
4964 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
4965 0, 0, 0 },
4966 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
4967 0, 0, DD_OK,
4968 DDSD_PITCH, 0x100, 0x0fc},
4969 /* 5 */
4970 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
4971 DDSD_PITCH, 0x104, DD_OK,
4972 DDSD_PITCH, 0x100, 0x0fc},
4973 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
4974 DDSD_PITCH, 0x0f8, DD_OK,
4975 DDSD_PITCH, 0x100, 0x0fc},
4976 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
4977 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
4978 DDSD_PITCH, 0x100, 0x0fc},
4979 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
4980 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
4981 0, 0, 0 },
4982 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
4983 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
4984 0, 0, 0 },
4985 /* 10 */
4986 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
4987 0, 0, DDERR_INVALIDCAPS,
4988 0, 0, 0 },
4989 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
4990 0, 0, DD_OK,
4991 DDSD_PITCH, 0x100, 0 },
4992 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
4993 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
4994 0, 0, 0 },
4995 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
4996 0, 0, DDERR_INVALIDCAPS,
4997 0, 0, 0 },
4998 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
4999 0, 0, DD_OK,
5000 DDSD_PITCH, 0x100, 0 },
5001 /* 15 */
5002 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
5003 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
5004 0, 0, 0 },
5006 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
5008 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5009 0, 0, 640, 480, 0, 0, 0, 0);
5010 ddraw = create_ddraw();
5011 ok(!!ddraw, "Failed to create a ddraw object.\n");
5012 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5013 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5015 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
5017 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
5019 memset(&surface_desc, 0, sizeof(surface_desc));
5020 surface_desc.dwSize = sizeof(surface_desc);
5021 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
5022 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
5023 surface_desc.dwWidth = 63;
5024 surface_desc.dwHeight = 63;
5025 U1(surface_desc).lPitch = test_data[i].pitch_in;
5026 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5027 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
5028 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
5029 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5030 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5031 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5032 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5033 if (test_data[i].flags_in & DDSD_LPSURFACE)
5035 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
5036 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
5037 surface_desc.lpSurface = mem;
5038 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5040 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
5041 continue;
5042 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
5043 if (FAILED(hr))
5044 continue;
5046 memset(&surface_desc, 0, sizeof(surface_desc));
5047 surface_desc.dwSize = sizeof(surface_desc);
5048 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
5049 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5050 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
5051 "Test %u: Got unexpected flags %#x, expected %#x.\n",
5052 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
5053 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
5055 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
5056 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
5057 "Test %u: Got unexpected pitch %u, expected %u.\n",
5058 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
5059 else
5060 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
5061 "Test %u: Got unexpected pitch %u, expected %u.\n",
5062 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
5064 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
5066 IDirectDrawSurface_Release(surface);
5069 HeapFree(GetProcessHeap(), 0, mem);
5070 refcount = IDirectDraw_Release(ddraw);
5071 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5072 DestroyWindow(window);
5075 static void test_mipmap(void)
5077 IDirectDrawSurface *surface, *surface2;
5078 DDSURFACEDESC surface_desc;
5079 IDirectDraw *ddraw;
5080 unsigned int i;
5081 ULONG refcount;
5082 HWND window;
5083 HRESULT hr;
5084 DDSCAPS caps = {DDSCAPS_COMPLEX};
5085 DDCAPS hal_caps;
5087 static const struct
5089 DWORD flags;
5090 DWORD caps;
5091 DWORD width;
5092 DWORD height;
5093 DWORD mipmap_count_in;
5094 HRESULT hr;
5095 DWORD mipmap_count_out;
5097 tests[] =
5099 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
5100 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
5101 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
5102 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
5103 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 6},
5104 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 6},
5107 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5108 0, 0, 640, 480, 0, 0, 0, 0);
5109 ddraw = create_ddraw();
5110 ok(!!ddraw, "Failed to create a ddraw object.\n");
5111 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5112 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5114 memset(&hal_caps, 0, sizeof(hal_caps));
5115 hal_caps.dwSize = sizeof(hal_caps);
5116 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
5117 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5118 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
5120 skip("Mipmapped textures not supported, skipping tests.\n");
5121 IDirectDraw_Release(ddraw);
5122 DestroyWindow(window);
5123 return;
5126 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
5128 memset(&surface_desc, 0, sizeof(surface_desc));
5129 surface_desc.dwSize = sizeof(surface_desc);
5130 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
5131 surface_desc.ddsCaps.dwCaps = tests[i].caps;
5132 surface_desc.dwWidth = tests[i].width;
5133 surface_desc.dwHeight = tests[i].height;
5134 if (tests[i].flags & DDSD_MIPMAPCOUNT)
5135 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
5136 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5137 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
5138 if (FAILED(hr))
5139 continue;
5141 memset(&surface_desc, 0, sizeof(surface_desc));
5142 surface_desc.dwSize = sizeof(surface_desc);
5143 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
5144 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5145 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
5146 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
5147 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
5148 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
5150 if (U2(surface_desc).dwMipMapCount > 1)
5152 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &surface2);
5153 ok(SUCCEEDED(hr), "Test %u: Failed to get attached surface, hr %#x.\n", i, hr);
5155 memset(&surface_desc, 0, sizeof(surface_desc));
5156 surface_desc.dwSize = sizeof(surface_desc);
5157 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, 0, NULL);
5158 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
5159 memset(&surface_desc, 0, sizeof(surface_desc));
5160 surface_desc.dwSize = sizeof(surface_desc);
5161 hr = IDirectDrawSurface_Lock(surface2, NULL, &surface_desc, 0, NULL);
5162 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
5163 IDirectDrawSurface_Unlock(surface2, NULL);
5164 IDirectDrawSurface_Unlock(surface, NULL);
5166 IDirectDrawSurface_Release(surface2);
5169 IDirectDrawSurface_Release(surface);
5172 refcount = IDirectDraw_Release(ddraw);
5173 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5174 DestroyWindow(window);
5177 static void test_palette_complex(void)
5179 IDirectDrawSurface *surface, *mipmap, *tmp;
5180 DDSURFACEDESC surface_desc;
5181 IDirectDraw *ddraw;
5182 IDirectDrawPalette *palette, *palette2, *palette_mipmap;
5183 ULONG refcount;
5184 HWND window;
5185 HRESULT hr;
5186 DDSCAPS caps = {DDSCAPS_COMPLEX};
5187 DDCAPS hal_caps;
5188 PALETTEENTRY palette_entries[256];
5189 unsigned int i;
5190 HDC dc;
5191 RGBQUAD rgbquad;
5192 UINT count;
5194 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5195 0, 0, 640, 480, 0, 0, 0, 0);
5196 ddraw = create_ddraw();
5197 ok(!!ddraw, "Failed to create a ddraw object.\n");
5198 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5199 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5201 memset(&hal_caps, 0, sizeof(hal_caps));
5202 hal_caps.dwSize = sizeof(hal_caps);
5203 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
5204 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5205 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
5207 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
5208 IDirectDraw_Release(ddraw);
5209 DestroyWindow(window);
5210 return;
5213 memset(&surface_desc, 0, sizeof(surface_desc));
5214 surface_desc.dwSize = sizeof(surface_desc);
5215 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5216 surface_desc.dwWidth = 128;
5217 surface_desc.dwHeight = 128;
5218 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
5219 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5220 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
5221 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
5222 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5223 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5225 memset(palette_entries, 0, sizeof(palette_entries));
5226 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
5227 palette_entries, &palette, NULL);
5228 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5230 memset(palette_entries, 0, sizeof(palette_entries));
5231 palette_entries[1].peRed = 0xff;
5232 palette_entries[1].peGreen = 0x80;
5233 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
5234 palette_entries, &palette_mipmap, NULL);
5235 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5237 palette2 = (void *)0xdeadbeef;
5238 hr = IDirectDrawSurface_GetPalette(surface, &palette2);
5239 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
5240 ok(!palette2, "Got unexpected palette %p.\n", palette2);
5241 hr = IDirectDrawSurface_SetPalette(surface, palette);
5242 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5243 hr = IDirectDrawSurface_GetPalette(surface, &palette2);
5244 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
5245 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
5246 IDirectDrawPalette_Release(palette2);
5248 mipmap = surface;
5249 IDirectDrawSurface_AddRef(mipmap);
5250 for (i = 0; i < 7; ++i)
5252 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
5253 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
5254 palette2 = (void *)0xdeadbeef;
5255 hr = IDirectDrawSurface_GetPalette(tmp, &palette2);
5256 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
5257 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
5259 hr = IDirectDrawSurface_SetPalette(tmp, palette_mipmap);
5260 ok(SUCCEEDED(hr), "Failed to set palette, i %u, hr %#x.\n", i, hr);
5262 hr = IDirectDrawSurface_GetPalette(tmp, &palette2);
5263 ok(SUCCEEDED(hr), "Failed to get palette, i %u, hr %#x.\n", i, hr);
5264 ok(palette_mipmap == palette2, "Got unexpected palette %p.\n", palette2);
5265 IDirectDrawPalette_Release(palette2);
5267 hr = IDirectDrawSurface_GetDC(tmp, &dc);
5268 ok(SUCCEEDED(hr), "Failed to get DC, i %u, hr %#x.\n", i, hr);
5269 count = GetDIBColorTable(dc, 1, 1, &rgbquad);
5270 ok(count == 1, "Expected count 1, got %u.\n", count);
5271 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x.\n", rgbquad.rgbRed);
5272 ok(rgbquad.rgbGreen == 0x80, "Expected rgbGreen = 0x80, got %#x.\n", rgbquad.rgbGreen);
5273 ok(rgbquad.rgbBlue == 0x0, "Expected rgbBlue = 0x0, got %#x.\n", rgbquad.rgbBlue);
5274 hr = IDirectDrawSurface_ReleaseDC(tmp, dc);
5275 ok(SUCCEEDED(hr), "Failed to release DC, i %u, hr %#x.\n", i, hr);
5277 IDirectDrawSurface_Release(mipmap);
5278 mipmap = tmp;
5281 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
5282 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5283 IDirectDrawSurface_Release(mipmap);
5284 refcount = IDirectDrawSurface_Release(surface);
5285 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5286 refcount = IDirectDrawPalette_Release(palette_mipmap);
5287 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5288 refcount = IDirectDrawPalette_Release(palette);
5289 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5291 refcount = IDirectDraw_Release(ddraw);
5292 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5293 DestroyWindow(window);
5296 static BOOL ddraw_is_warp(IDirectDraw *ddraw)
5298 IDirectDraw4 *ddraw4;
5299 DDDEVICEIDENTIFIER identifier;
5300 HRESULT hr;
5302 if (!strcmp(winetest_platform, "wine"))
5303 return FALSE;
5305 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw4, (void **)&ddraw4);
5306 ok(SUCCEEDED(hr), "Failed to get IDirectDraw4 interface, hr %#x.\n", hr);
5307 hr = IDirectDraw4_GetDeviceIdentifier(ddraw4, &identifier, 0);
5308 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
5309 IDirectDraw4_Release(ddraw4);
5310 return !!strstr(identifier.szDriver, "warp");
5313 static void test_p8_blit(void)
5315 IDirectDrawSurface *src, *dst, *dst_p8;
5316 DDSURFACEDESC surface_desc;
5317 IDirectDraw *ddraw;
5318 IDirectDrawPalette *palette, *palette2;
5319 ULONG refcount;
5320 HWND window;
5321 HRESULT hr;
5322 PALETTEENTRY palette_entries[256];
5323 unsigned int x;
5324 DDBLTFX fx;
5325 BOOL is_warp;
5326 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
5327 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
5328 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
5329 static const D3DCOLOR expected[] =
5331 0x00101010, 0x00010101, 0x00020202, 0x00030303,
5332 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
5334 D3DCOLOR color;
5336 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5337 0, 0, 640, 480, 0, 0, 0, 0);
5338 ddraw = create_ddraw();
5339 ok(!!ddraw, "Failed to create a ddraw object.\n");
5340 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5341 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5342 is_warp = ddraw_is_warp(ddraw);
5344 memset(palette_entries, 0, sizeof(palette_entries));
5345 palette_entries[1].peGreen = 0xff;
5346 palette_entries[2].peBlue = 0xff;
5347 palette_entries[3].peFlags = 0xff;
5348 palette_entries[4].peRed = 0xff;
5349 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
5350 palette_entries, &palette, NULL);
5351 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5352 palette_entries[1].peBlue = 0xff;
5353 palette_entries[2].peGreen = 0xff;
5354 palette_entries[3].peRed = 0xff;
5355 palette_entries[4].peFlags = 0x0;
5356 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
5357 palette_entries, &palette2, NULL);
5358 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5360 memset(&surface_desc, 0, sizeof(surface_desc));
5361 surface_desc.dwSize = sizeof(surface_desc);
5362 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5363 surface_desc.dwWidth = 8;
5364 surface_desc.dwHeight = 1;
5365 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5366 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5367 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
5368 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
5369 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src, NULL);
5370 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5371 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
5372 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5373 hr = IDirectDrawSurface_SetPalette(dst_p8, palette2);
5374 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5376 memset(&surface_desc, 0, sizeof(surface_desc));
5377 surface_desc.dwSize = sizeof(surface_desc);
5378 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5379 surface_desc.dwWidth = 8;
5380 surface_desc.dwHeight = 1;
5381 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5382 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5383 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
5384 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
5385 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5386 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5387 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5388 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
5389 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst, NULL);
5390 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5392 memset(&surface_desc, 0, sizeof(surface_desc));
5393 surface_desc.dwSize = sizeof(surface_desc);
5394 hr = IDirectDrawSurface_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
5395 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
5396 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
5397 hr = IDirectDrawSurface_Unlock(src, NULL);
5398 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
5400 hr = IDirectDrawSurface_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
5401 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
5402 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
5403 hr = IDirectDrawSurface_Unlock(dst_p8, NULL);
5404 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
5406 hr = IDirectDrawSurface_SetPalette(src, palette);
5407 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5408 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
5409 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
5410 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
5411 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
5412 "Failed to blit, hr %#x.\n", hr);
5414 if (SUCCEEDED(hr))
5416 for (x = 0; x < sizeof(expected) / sizeof(*expected); x++)
5418 color = get_surface_color(dst, x, 0);
5419 todo_wine ok(compare_color(color, expected[x], 0),
5420 "Pixel %u: Got color %#x, expected %#x.\n",
5421 x, color, expected[x]);
5425 memset(&fx, 0, sizeof(fx));
5426 fx.dwSize = sizeof(fx);
5427 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
5428 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
5429 hr = IDirectDrawSurface_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
5430 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
5432 hr = IDirectDrawSurface_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
5433 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
5434 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
5435 * surface untouched. P8 blits without color keys work. Error checking (DDBLT_KEYSRC without a key
5436 * for example) also works as expected.
5438 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
5439 * the display mode set to P8 doesn't help either. */
5440 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
5441 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
5442 "Got unexpected P8 color key blit result.\n");
5443 hr = IDirectDrawSurface_Unlock(dst_p8, NULL);
5444 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
5446 IDirectDrawSurface_Release(src);
5447 IDirectDrawSurface_Release(dst);
5448 IDirectDrawSurface_Release(dst_p8);
5449 IDirectDrawPalette_Release(palette);
5450 IDirectDrawPalette_Release(palette2);
5452 refcount = IDirectDraw_Release(ddraw);
5453 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5454 DestroyWindow(window);
5457 static void test_material(void)
5459 IDirect3DMaterial *background, *material;
5460 IDirect3DExecuteBuffer *execute_buffer;
5461 D3DMATERIALHANDLE mat_handle, tmp;
5462 D3DEXECUTEBUFFERDESC exec_desc;
5463 IDirect3DViewport *viewport;
5464 IDirect3DDevice *device;
5465 IDirectDrawSurface *rt;
5466 IDirectDraw *ddraw;
5467 UINT inst_length;
5468 D3DCOLOR color;
5469 ULONG refcount;
5470 unsigned int i;
5471 HWND window;
5472 HRESULT hr;
5473 BOOL valid;
5474 void *ptr;
5476 static D3DVERTEX quad[] =
5478 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5479 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5480 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5481 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5483 static const struct
5485 BOOL material;
5486 D3DCOLOR expected_color;
5488 test_data[] =
5490 {TRUE, 0x0000ff00},
5491 {FALSE, 0x00ffffff},
5493 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
5495 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5496 0, 0, 640, 480, 0, 0, 0, 0);
5497 ddraw = create_ddraw();
5498 ok(!!ddraw, "Failed to create a ddraw object.\n");
5499 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
5501 skip("Failed to create a 3D device, skipping test.\n");
5502 DestroyWindow(window);
5503 return;
5506 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
5507 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5509 background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
5510 viewport = create_viewport(device, 0, 0, 640, 480);
5511 viewport_set_background(device, viewport, background);
5513 material = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
5514 hr = IDirect3DMaterial_GetHandle(material, device, &mat_handle);
5515 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
5517 memset(&exec_desc, 0, sizeof(exec_desc));
5518 exec_desc.dwSize = sizeof(exec_desc);
5519 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
5520 exec_desc.dwBufferSize = 1024;
5521 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
5523 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
5524 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
5526 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
5528 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
5529 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
5531 memcpy(exec_desc.lpData, quad, sizeof(quad));
5532 ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad);
5533 emit_set_ls(&ptr, D3DLIGHTSTATE_MATERIAL, test_data[i].material ? mat_handle : 0);
5534 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
5535 emit_tquad(&ptr, 0);
5536 emit_end(&ptr);
5537 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
5538 inst_length -= sizeof(quad);
5540 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
5541 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
5543 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
5544 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
5546 hr = IDirect3DDevice_BeginScene(device);
5547 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5548 set_execute_data(execute_buffer, 4, sizeof(quad), inst_length);
5549 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
5550 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
5551 hr = IDirect3DDevice_EndScene(device);
5552 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5553 color = get_surface_color(rt, 320, 240);
5554 if (test_data[i].material)
5555 todo_wine ok(compare_color(color, test_data[i].expected_color, 1)
5556 /* The Windows 8 testbot appears to return undefined results. */
5557 || broken(TRUE),
5558 "Got unexpected color 0x%08x, test %u.\n", color, i);
5559 else
5560 ok(compare_color(color, test_data[i].expected_color, 1),
5561 "Got unexpected color 0x%08x, test %u.\n", color, i);
5564 destroy_material(material);
5565 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
5566 hr = IDirect3DMaterial_GetHandle(material, device, &mat_handle);
5567 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
5569 hr = IDirect3DViewport_SetBackground(viewport, mat_handle);
5570 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
5571 hr = IDirect3DViewport_GetBackground(viewport, &tmp, &valid);
5572 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
5573 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
5574 ok(valid, "Got unexpected valid %#x.\n", valid);
5575 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
5576 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
5577 color = get_surface_color(rt, 320, 240);
5578 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
5580 hr = IDirect3DViewport_SetBackground(viewport, 0);
5581 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
5582 hr = IDirect3DViewport_GetBackground(viewport, &tmp, &valid);
5583 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
5584 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
5585 ok(valid, "Got unexpected valid %#x.\n", valid);
5586 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
5587 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
5588 color = get_surface_color(rt, 320, 240);
5589 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
5591 destroy_viewport(device, viewport);
5592 viewport = create_viewport(device, 0, 0, 640, 480);
5594 hr = IDirect3DViewport_GetBackground(viewport, &tmp, &valid);
5595 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
5596 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
5597 ok(!valid, "Got unexpected valid %#x.\n", valid);
5598 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
5599 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
5600 color = get_surface_color(rt, 320, 240);
5601 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x.\n", color);
5603 IDirect3DExecuteBuffer_Release(execute_buffer);
5604 destroy_viewport(device, viewport);
5605 destroy_material(background);
5606 destroy_material(material);
5607 IDirectDrawSurface_Release(rt);
5608 refcount = IDirect3DDevice_Release(device);
5609 ok(!refcount, "Device has %u references left.\n", refcount);
5610 refcount = IDirectDraw_Release(ddraw);
5611 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
5612 DestroyWindow(window);
5615 static void test_lighting(void)
5617 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
5618 static D3DMATRIX mat =
5620 1.0f, 0.0f, 0.0f, 0.0f,
5621 0.0f, 1.0f, 0.0f, 0.0f,
5622 0.0f, 0.0f, 1.0f, 0.0f,
5623 0.0f, 0.0f, 0.0f, 1.0f,
5625 mat_singular =
5627 1.0f, 0.0f, 1.0f, 0.0f,
5628 0.0f, 1.0f, 0.0f, 0.0f,
5629 1.0f, 0.0f, 1.0f, 0.0f,
5630 0.0f, 0.0f, 0.5f, 1.0f,
5632 mat_transf =
5634 0.0f, 0.0f, 1.0f, 0.0f,
5635 0.0f, 1.0f, 0.0f, 0.0f,
5636 -1.0f, 0.0f, 0.0f, 0.0f,
5637 10.f, 10.0f, 10.0f, 1.0f,
5639 mat_nonaffine =
5641 1.0f, 0.0f, 0.0f, 0.0f,
5642 0.0f, 1.0f, 0.0f, 0.0f,
5643 0.0f, 0.0f, 1.0f, -1.0f,
5644 10.f, 10.0f, 10.0f, 0.0f,
5646 static D3DLVERTEX unlitquad[] =
5648 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
5649 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
5650 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
5651 {{ 0.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
5653 litquad[] =
5655 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
5656 {{-1.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
5657 {{ 0.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
5658 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
5660 static D3DVERTEX unlitnquad[] =
5662 {{0.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5663 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5664 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5665 {{1.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5667 litnquad[] =
5669 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5670 {{0.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5671 {{1.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5672 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
5674 nquad[] =
5676 {{-1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5677 {{-1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5678 {{ 1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5679 {{ 1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5681 rotatedquad[] =
5683 {{-10.0f}, {-11.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
5684 {{-10.0f}, { -9.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
5685 {{-10.0f}, { -9.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
5686 {{-10.0f}, {-11.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
5688 translatedquad[] =
5690 {{-11.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5691 {{-11.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5692 {{ -9.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5693 {{ -9.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
5695 static const struct
5697 D3DMATRIX *world_matrix;
5698 void *quad;
5699 DWORD expected;
5700 const char *message;
5702 tests[] =
5704 {&mat, nquad, 0x000000ff, "Lit quad with light"},
5705 {&mat_singular, nquad, 0x000000b4, "Lit quad with singular world matrix"},
5706 {&mat_transf, rotatedquad, 0x000000ff, "Lit quad with transformation matrix"},
5707 {&mat_nonaffine, translatedquad, 0x000000ff, "Lit quad with non-affine matrix"},
5710 HWND window;
5711 IDirect3D *d3d;
5712 IDirect3DDevice *device;
5713 IDirectDraw *ddraw;
5714 IDirectDrawSurface *rt;
5715 IDirect3DViewport *viewport;
5716 IDirect3DMaterial *material;
5717 IDirect3DLight *light;
5718 IDirect3DExecuteBuffer *execute_buffer;
5719 D3DEXECUTEBUFFERDESC exec_desc;
5720 D3DMATERIALHANDLE mat_handle;
5721 D3DMATRIXHANDLE world_handle, view_handle, proj_handle;
5722 D3DLIGHT light_desc;
5723 HRESULT hr;
5724 D3DCOLOR color;
5725 void *ptr;
5726 UINT inst_length;
5727 ULONG refcount;
5728 unsigned int i;
5730 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5731 0, 0, 640, 480, 0, 0, 0, 0);
5732 ddraw = create_ddraw();
5733 ok(!!ddraw, "Failed to create a ddraw object.\n");
5734 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
5736 skip("Failed to create a 3D device, skipping test.\n");
5737 IDirectDraw_Release(ddraw);
5738 DestroyWindow(window);
5739 return;
5742 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
5743 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
5745 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
5746 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5748 viewport = create_viewport(device, 0, 0, 640, 480);
5749 material = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
5750 viewport_set_background(device, viewport, material);
5752 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
5753 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
5755 hr = IDirect3DDevice_CreateMatrix(device, &world_handle);
5756 ok(hr == D3D_OK, "Creating a matrix object failed, hr %#x.\n", hr);
5757 hr = IDirect3DDevice_SetMatrix(device, world_handle, &mat);
5758 ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
5759 hr = IDirect3DDevice_CreateMatrix(device, &view_handle);
5760 ok(hr == D3D_OK, "Creating a matrix object failed, hr %#x.\n", hr);
5761 hr = IDirect3DDevice_SetMatrix(device, view_handle, &mat);
5762 ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
5763 hr = IDirect3DDevice_CreateMatrix(device, &proj_handle);
5764 ok(hr == D3D_OK, "Creating a matrix object failed, hr %#x.\n", hr);
5765 hr = IDirect3DDevice_SetMatrix(device, proj_handle, &mat);
5766 ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
5768 memset(&exec_desc, 0, sizeof(exec_desc));
5769 exec_desc.dwSize = sizeof(exec_desc);
5770 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
5771 exec_desc.dwBufferSize = 1024;
5772 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
5774 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
5775 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
5777 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
5778 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
5780 memcpy(exec_desc.lpData, unlitquad, sizeof(unlitquad));
5781 ptr = ((BYTE *)exec_desc.lpData) + sizeof(unlitquad);
5782 emit_set_ts(&ptr, D3DTRANSFORMSTATE_WORLD, world_handle);
5783 emit_set_ts(&ptr, D3DTRANSFORMSTATE_VIEW, view_handle);
5784 emit_set_ts(&ptr, D3DTRANSFORMSTATE_PROJECTION, proj_handle);
5785 emit_set_rs(&ptr, D3DRENDERSTATE_CLIPPING, FALSE);
5786 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, FALSE);
5787 emit_set_rs(&ptr, D3DRENDERSTATE_FOGENABLE, FALSE);
5788 emit_set_rs(&ptr, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
5789 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
5790 emit_tquad_tlist(&ptr, 0);
5791 emit_end(&ptr);
5792 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
5793 inst_length -= sizeof(unlitquad);
5795 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
5796 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
5798 hr = IDirect3DDevice_BeginScene(device);
5799 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5801 set_execute_data(execute_buffer, 4, sizeof(unlitquad), inst_length);
5802 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
5803 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
5805 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
5806 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
5808 memcpy(exec_desc.lpData, litquad, sizeof(litquad));
5809 ptr = ((BYTE *)exec_desc.lpData) + sizeof(litquad);
5810 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
5811 emit_tquad_tlist(&ptr, 0);
5812 emit_end(&ptr);
5813 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
5814 inst_length -= sizeof(litquad);
5816 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
5817 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
5819 set_execute_data(execute_buffer, 4, sizeof(litquad), inst_length);
5820 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
5821 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
5823 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
5824 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
5826 memcpy(exec_desc.lpData, unlitnquad, sizeof(unlitnquad));
5827 ptr = ((BYTE *)exec_desc.lpData) + sizeof(unlitnquad);
5828 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
5829 emit_tquad_tlist(&ptr, 0);
5830 emit_end(&ptr);
5831 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
5832 inst_length -= sizeof(unlitnquad);
5834 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
5835 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
5837 set_execute_data(execute_buffer, 4, sizeof(unlitnquad), inst_length);
5838 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
5839 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
5841 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
5842 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
5844 memcpy(exec_desc.lpData, litnquad, sizeof(litnquad));
5845 ptr = ((BYTE *)exec_desc.lpData) + sizeof(litnquad);
5846 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
5847 emit_tquad_tlist(&ptr, 0);
5848 emit_end(&ptr);
5849 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
5850 inst_length -= sizeof(litnquad);
5852 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
5853 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
5855 set_execute_data(execute_buffer, 4, sizeof(litnquad), inst_length);
5856 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
5857 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
5859 hr = IDirect3DDevice_EndScene(device);
5860 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5862 color = get_surface_color(rt, 160, 360);
5863 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
5864 color = get_surface_color(rt, 160, 120);
5865 ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
5866 color = get_surface_color(rt, 480, 360);
5867 ok(color == 0x00ffffff, "Unlit quad with normals has color 0x%08x.\n", color);
5868 color = get_surface_color(rt, 480, 120);
5869 ok(color == 0x00ffffff, "Lit quad with normals has color 0x%08x.\n", color);
5871 hr = IDirect3DMaterial_GetHandle(material, device, &mat_handle);
5872 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
5874 hr = IDirect3D_CreateLight(d3d, &light, NULL);
5875 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
5876 memset(&light_desc, 0, sizeof(light_desc));
5877 light_desc.dwSize = sizeof(light_desc);
5878 light_desc.dltType = D3DLIGHT_DIRECTIONAL;
5879 U1(light_desc.dcvColor).r = 0.0f;
5880 U2(light_desc.dcvColor).g = 0.0f;
5881 U3(light_desc.dcvColor).b = 1.0f;
5882 U4(light_desc.dcvColor).a = 1.0f;
5883 U3(light_desc.dvDirection).z = 1.0f;
5884 hr = IDirect3DLight_SetLight(light, &light_desc);
5885 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
5886 hr = IDirect3DViewport_AddLight(viewport, light);
5887 ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
5889 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
5891 hr = IDirect3DDevice_SetMatrix(device, world_handle, tests[i].world_matrix);
5892 ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
5894 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
5895 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
5897 hr = IDirect3DDevice_BeginScene(device);
5898 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5900 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
5901 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
5903 memcpy(exec_desc.lpData, tests[i].quad, sizeof(nquad));
5904 ptr = ((BYTE *)exec_desc.lpData) + sizeof(nquad);
5905 emit_set_ls(&ptr, D3DLIGHTSTATE_MATERIAL, mat_handle);
5906 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
5907 emit_tquad_tlist(&ptr, 0);
5908 emit_end(&ptr);
5909 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
5910 inst_length -= sizeof(nquad);
5912 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
5913 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
5915 set_execute_data(execute_buffer, 4, sizeof(nquad), inst_length);
5916 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
5917 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
5919 hr = IDirect3DDevice_EndScene(device);
5920 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5922 color = get_surface_color(rt, 320, 240);
5923 todo_wine ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
5926 IDirect3DExecuteBuffer_Release(execute_buffer);
5927 IDirect3DDevice_DeleteMatrix(device, world_handle);
5928 IDirect3DDevice_DeleteMatrix(device, view_handle);
5929 IDirect3DDevice_DeleteMatrix(device, proj_handle);
5930 hr = IDirect3DViewport_DeleteLight(viewport, light);
5931 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
5932 IDirect3DLight_Release(light);
5933 destroy_material(material);
5934 destroy_viewport(device, viewport);
5935 IDirectDrawSurface_Release(rt);
5936 refcount = IDirect3DDevice_Release(device);
5937 ok(!refcount, "Device has %u references left.\n", refcount);
5938 IDirect3D_Release(d3d);
5939 refcount = IDirectDraw_Release(ddraw);
5940 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
5941 DestroyWindow(window);
5944 static void test_palette_gdi(void)
5946 IDirectDrawSurface *surface, *primary;
5947 DDSURFACEDESC surface_desc;
5948 IDirectDraw *ddraw;
5949 IDirectDrawPalette *palette, *palette2;
5950 ULONG refcount;
5951 HWND window;
5952 HRESULT hr;
5953 PALETTEENTRY palette_entries[256];
5954 UINT i;
5955 HDC dc;
5956 DDBLTFX fx;
5957 RECT r;
5958 COLORREF color;
5959 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
5960 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
5961 * not the point of this test. */
5962 static const RGBQUAD expected1[] =
5964 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
5965 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
5967 static const RGBQUAD expected2[] =
5969 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
5970 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
5972 static const RGBQUAD expected3[] =
5974 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
5975 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
5977 HPALETTE ddraw_palette_handle;
5978 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
5979 RGBQUAD rgbquad[255];
5980 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
5982 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5983 0, 0, 640, 480, 0, 0, 0, 0);
5984 ddraw = create_ddraw();
5985 ok(!!ddraw, "Failed to create a ddraw object.\n");
5986 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5987 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5989 memset(&surface_desc, 0, sizeof(surface_desc));
5990 surface_desc.dwSize = sizeof(surface_desc);
5991 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5992 surface_desc.dwWidth = 16;
5993 surface_desc.dwHeight = 16;
5994 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5995 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5996 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
5997 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
5998 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5999 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6001 /* Avoid colors from the Windows default palette. */
6002 memset(palette_entries, 0, sizeof(palette_entries));
6003 palette_entries[1].peRed = 0x01;
6004 palette_entries[2].peGreen = 0x02;
6005 palette_entries[3].peBlue = 0x03;
6006 palette_entries[4].peRed = 0x13;
6007 palette_entries[4].peGreen = 0x14;
6008 palette_entries[4].peBlue = 0x15;
6009 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6010 palette_entries, &palette, NULL);
6011 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6013 /* If there is no palette assigned and the display mode is not 8 bpp, some
6014 * drivers refuse to create a DC while others allow it. If a DC is created,
6015 * the DIB color table is uninitialized and contains random colors. No error
6016 * is generated when trying to read pixels and random garbage is returned.
6018 * The most likely explanation is that if the driver creates a DC, it (or
6019 * the higher-level runtime) uses GetSystemPaletteEntries to find the
6020 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
6021 * contains uninitialized garbage. See comments below for the P8 case. */
6023 hr = IDirectDrawSurface_SetPalette(surface, palette);
6024 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6025 hr = IDirectDrawSurface_GetDC(surface, &dc);
6026 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6027 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
6028 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
6029 "Got unexpected palette %p, expected %p.\n",
6030 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
6032 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
6033 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
6034 for (i = 0; i < sizeof(expected1) / sizeof(*expected1); i++)
6036 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
6037 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
6038 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
6039 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
6041 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
6043 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
6044 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
6045 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
6048 /* Update the palette while the DC is in use. This does not modify the DC. */
6049 palette_entries[4].peRed = 0x23;
6050 palette_entries[4].peGreen = 0x24;
6051 palette_entries[4].peBlue = 0x25;
6052 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
6053 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
6055 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
6056 ok(i == 1, "Expected count 1, got %u.\n", i);
6057 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
6058 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
6059 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
6060 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
6062 /* Neither does re-setting the palette. */
6063 hr = IDirectDrawSurface_SetPalette(surface, NULL);
6064 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6065 hr = IDirectDrawSurface_SetPalette(surface, palette);
6066 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6068 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
6069 ok(i == 1, "Expected count 1, got %u.\n", i);
6070 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
6071 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
6072 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
6073 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
6075 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
6076 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6078 /* Refresh the DC. This updates the palette. */
6079 hr = IDirectDrawSurface_GetDC(surface, &dc);
6080 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6081 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
6082 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
6083 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
6085 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
6086 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
6087 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
6088 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
6090 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
6092 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
6093 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
6094 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
6096 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
6097 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6099 refcount = IDirectDrawSurface_Release(surface);
6100 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6102 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
6103 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6104 if (FAILED(IDirectDraw_SetDisplayMode(ddraw, 640, 480, 8)))
6106 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
6107 IDirectDrawPalette_Release(palette);
6108 IDirectDraw_Release(ddraw);
6109 DestroyWindow(window);
6110 return;
6112 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
6114 memset(&surface_desc, 0, sizeof(surface_desc));
6115 surface_desc.dwSize = sizeof(surface_desc);
6116 surface_desc.dwFlags = DDSD_CAPS;
6117 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
6118 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
6119 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6121 memset(&fx, 0, sizeof(fx));
6122 fx.dwSize = sizeof(fx);
6123 fx.dwFillColor = 3;
6124 SetRect(&r, 0, 0, 319, 479);
6125 hr = IDirectDrawSurface_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6126 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
6127 SetRect(&r, 320, 0, 639, 479);
6128 fx.dwFillColor = 4;
6129 hr = IDirectDrawSurface_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6130 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
6132 hr = IDirectDrawSurface_SetPalette(primary, palette);
6133 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6134 hr = IDirectDrawSurface_GetDC(primary, &dc);
6135 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6137 color = GetPixel(dc, 160, 240);
6138 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
6139 color = GetPixel(dc, 480, 240);
6140 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
6142 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
6143 /* Windows 2000 on the testbot assigns a different palette to the primary. Refrast? */
6144 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE) || broken(TRUE),
6145 "Got unexpected palette %p, expected %p.\n",
6146 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
6147 SelectPalette(dc, ddraw_palette_handle, FALSE);
6149 /* The primary uses the system palette. In exclusive mode, the system palette matches
6150 * the ddraw palette attached to the primary, so the result is what you would expect
6151 * from a regular surface. Tests for the interaction between the ddraw palette and
6152 * the system palette are not included pending an application that depends on this.
6153 * The relation between those causes problems on Windows Vista and newer for games
6154 * like Age of Empires or StarCraft. Don't emulate it without a real need. */
6155 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
6156 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
6157 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
6159 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
6160 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
6161 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
6162 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
6164 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
6166 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
6167 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
6168 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
6170 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
6171 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6173 memset(&surface_desc, 0, sizeof(surface_desc));
6174 surface_desc.dwSize = sizeof(surface_desc);
6175 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6176 surface_desc.dwWidth = 16;
6177 surface_desc.dwHeight = 16;
6178 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6179 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6180 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6182 /* Here the offscreen surface appears to use the primary's palette,
6183 * but in all likelihood it is actually the system palette. */
6184 hr = IDirectDrawSurface_GetDC(surface, &dc);
6185 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6186 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
6187 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
6188 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
6190 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
6191 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
6192 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
6193 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
6195 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
6197 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
6198 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
6199 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
6201 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
6202 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6204 /* On real hardware a change to the primary surface's palette applies immediately,
6205 * even on device contexts from offscreen surfaces that do not have their own
6206 * palette. On the testbot VMs this is not the case. Don't test this until we
6207 * know of an application that depends on this. */
6209 memset(palette_entries, 0, sizeof(palette_entries));
6210 palette_entries[1].peBlue = 0x40;
6211 palette_entries[2].peRed = 0x40;
6212 palette_entries[3].peGreen = 0x40;
6213 palette_entries[4].peRed = 0x12;
6214 palette_entries[4].peGreen = 0x34;
6215 palette_entries[4].peBlue = 0x56;
6216 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6217 palette_entries, &palette2, NULL);
6218 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6219 hr = IDirectDrawSurface_SetPalette(surface, palette2);
6220 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6222 /* A palette assigned to the offscreen surface overrides the primary / system
6223 * palette. */
6224 hr = IDirectDrawSurface_GetDC(surface, &dc);
6225 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6226 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
6227 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
6228 for (i = 0; i < sizeof(expected3) / sizeof(*expected3); i++)
6230 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
6231 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
6232 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
6233 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
6235 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
6237 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
6238 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
6239 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
6241 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
6242 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6244 refcount = IDirectDrawSurface_Release(surface);
6245 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6247 /* The Windows 8 testbot keeps extra references to the primary and
6248 * backbuffer while in 8 bpp mode. */
6249 hr = IDirectDraw_RestoreDisplayMode(ddraw);
6250 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
6252 refcount = IDirectDrawSurface_Release(primary);
6253 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6254 refcount = IDirectDrawPalette_Release(palette2);
6255 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6256 refcount = IDirectDrawPalette_Release(palette);
6257 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6258 refcount = IDirectDraw_Release(ddraw);
6259 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6260 DestroyWindow(window);
6263 static void test_palette_alpha(void)
6265 IDirectDrawSurface *surface;
6266 DDSURFACEDESC surface_desc;
6267 IDirectDraw *ddraw;
6268 IDirectDrawPalette *palette;
6269 ULONG refcount;
6270 HWND window;
6271 HRESULT hr;
6272 PALETTEENTRY palette_entries[256];
6273 unsigned int i;
6274 static const struct
6276 DWORD caps, flags;
6277 BOOL attach_allowed;
6278 const char *name;
6280 test_data[] =
6282 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
6283 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
6284 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
6287 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6288 0, 0, 640, 480, 0, 0, 0, 0);
6289 ddraw = create_ddraw();
6290 ok(!!ddraw, "Failed to create a ddraw object.\n");
6291 if (FAILED(IDirectDraw_SetDisplayMode(ddraw, 640, 480, 8)))
6293 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
6294 IDirectDraw_Release(ddraw);
6295 DestroyWindow(window);
6296 return;
6298 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6299 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6301 memset(palette_entries, 0, sizeof(palette_entries));
6302 palette_entries[1].peFlags = 0x42;
6303 palette_entries[2].peFlags = 0xff;
6304 palette_entries[3].peFlags = 0x80;
6305 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
6306 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6308 memset(palette_entries, 0x66, sizeof(palette_entries));
6309 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
6310 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
6311 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
6312 palette_entries[0].peFlags);
6313 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
6314 palette_entries[1].peFlags);
6315 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
6316 palette_entries[2].peFlags);
6317 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
6318 palette_entries[3].peFlags);
6320 IDirectDrawPalette_Release(palette);
6322 memset(palette_entries, 0, sizeof(palette_entries));
6323 palette_entries[1].peFlags = 0x42;
6324 palette_entries[1].peRed = 0xff;
6325 palette_entries[2].peFlags = 0xff;
6326 palette_entries[3].peFlags = 0x80;
6327 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
6328 palette_entries, &palette, NULL);
6329 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6331 memset(palette_entries, 0x66, sizeof(palette_entries));
6332 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
6333 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
6334 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
6335 palette_entries[0].peFlags);
6336 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
6337 palette_entries[1].peFlags);
6338 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
6339 palette_entries[2].peFlags);
6340 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
6341 palette_entries[3].peFlags);
6343 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
6345 memset(&surface_desc, 0, sizeof(surface_desc));
6346 surface_desc.dwSize = sizeof(surface_desc);
6347 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
6348 surface_desc.dwWidth = 128;
6349 surface_desc.dwHeight = 128;
6350 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
6351 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6352 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
6354 hr = IDirectDrawSurface_SetPalette(surface, palette);
6355 if (test_data[i].attach_allowed)
6356 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
6357 else
6358 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
6360 if (SUCCEEDED(hr))
6362 HDC dc;
6363 RGBQUAD rgbquad;
6364 UINT retval;
6366 hr = IDirectDrawSurface_GetDC(surface, &dc);
6367 ok(SUCCEEDED(hr) || broken(hr == DDERR_CANTCREATEDC) /* Win2k testbot */,
6368 "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
6369 if (SUCCEEDED(hr))
6371 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
6372 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
6373 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
6374 rgbquad.rgbRed, test_data[i].name);
6375 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
6376 rgbquad.rgbGreen, test_data[i].name);
6377 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
6378 rgbquad.rgbBlue, test_data[i].name);
6379 todo_wine ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
6380 rgbquad.rgbReserved, test_data[i].name);
6381 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
6382 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6385 IDirectDrawSurface_Release(surface);
6388 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
6389 memset(&surface_desc, 0, sizeof(surface_desc));
6390 surface_desc.dwSize = sizeof(surface_desc);
6391 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6392 surface_desc.dwWidth = 128;
6393 surface_desc.dwHeight = 128;
6394 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6395 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6396 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
6397 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
6398 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6399 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6400 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6401 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6402 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6403 hr = IDirectDrawSurface_SetPalette(surface, palette);
6404 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
6405 IDirectDrawSurface_Release(surface);
6407 /* The Windows 8 testbot keeps extra references to the primary
6408 * while in 8 bpp mode. */
6409 hr = IDirectDraw_RestoreDisplayMode(ddraw);
6410 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
6412 refcount = IDirectDrawPalette_Release(palette);
6413 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6414 refcount = IDirectDraw_Release(ddraw);
6415 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6416 DestroyWindow(window);
6419 static void test_lost_device(void)
6421 IDirectDrawSurface *surface;
6422 DDSURFACEDESC surface_desc;
6423 HWND window1, window2;
6424 IDirectDraw *ddraw;
6425 ULONG refcount;
6426 HRESULT hr;
6427 BOOL ret;
6429 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6430 0, 0, 640, 480, 0, 0, 0, 0);
6431 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6432 0, 0, 640, 480, 0, 0, 0, 0);
6433 ddraw = create_ddraw();
6434 ok(!!ddraw, "Failed to create a ddraw object.\n");
6435 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6436 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6438 memset(&surface_desc, 0, sizeof(surface_desc));
6439 surface_desc.dwSize = sizeof(surface_desc);
6440 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6441 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6442 surface_desc.dwBackBufferCount = 1;
6443 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6444 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6446 hr = IDirectDrawSurface_IsLost(surface);
6447 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6448 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6449 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6451 ret = SetForegroundWindow(GetDesktopWindow());
6452 ok(ret, "Failed to set foreground window.\n");
6453 hr = IDirectDrawSurface_IsLost(surface);
6454 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6455 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6456 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6458 ret = SetForegroundWindow(window1);
6459 ok(ret, "Failed to set foreground window.\n");
6460 hr = IDirectDrawSurface_IsLost(surface);
6461 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6462 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6463 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6465 hr = restore_surfaces(ddraw);
6466 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6467 hr = IDirectDrawSurface_IsLost(surface);
6468 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6469 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6470 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6472 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
6473 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6474 hr = IDirectDrawSurface_IsLost(surface);
6475 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6476 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6477 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
6479 /* Trying to restore the primary will crash, probably because flippable
6480 * surfaces can't exist in DDSCL_NORMAL. */
6481 IDirectDrawSurface_Release(surface);
6482 memset(&surface_desc, 0, sizeof(surface_desc));
6483 surface_desc.dwSize = sizeof(surface_desc);
6484 surface_desc.dwFlags = DDSD_CAPS;
6485 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
6486 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6487 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6489 hr = IDirectDrawSurface_IsLost(surface);
6490 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6492 ret = SetForegroundWindow(GetDesktopWindow());
6493 ok(ret, "Failed to set foreground window.\n");
6494 hr = IDirectDrawSurface_IsLost(surface);
6495 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6497 ret = SetForegroundWindow(window1);
6498 ok(ret, "Failed to set foreground window.\n");
6499 hr = IDirectDrawSurface_IsLost(surface);
6500 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6502 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6503 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6504 hr = IDirectDrawSurface_IsLost(surface);
6505 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6507 hr = restore_surfaces(ddraw);
6508 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6509 hr = IDirectDrawSurface_IsLost(surface);
6510 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6512 IDirectDrawSurface_Release(surface);
6513 memset(&surface_desc, 0, sizeof(surface_desc));
6514 surface_desc.dwSize = sizeof(surface_desc);
6515 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6516 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6517 U5(surface_desc).dwBackBufferCount = 1;
6518 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6519 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6521 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6522 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6523 hr = IDirectDrawSurface_IsLost(surface);
6524 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6525 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6526 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6528 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
6529 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6530 hr = IDirectDrawSurface_IsLost(surface);
6531 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6532 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6533 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
6535 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
6536 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6537 hr = IDirectDrawSurface_IsLost(surface);
6538 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6539 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6540 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
6542 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
6543 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6544 hr = IDirectDrawSurface_IsLost(surface);
6545 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6546 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6547 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
6549 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
6550 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6551 hr = IDirectDrawSurface_IsLost(surface);
6552 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6553 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6554 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
6556 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6557 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6558 hr = IDirectDrawSurface_IsLost(surface);
6559 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6560 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
6561 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6563 IDirectDrawSurface_Release(surface);
6564 refcount = IDirectDraw_Release(ddraw);
6565 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6566 DestroyWindow(window2);
6567 DestroyWindow(window1);
6570 static void test_surface_desc_lock(void)
6572 IDirectDrawSurface *surface;
6573 DDSURFACEDESC surface_desc;
6574 IDirectDraw *ddraw;
6575 ULONG refcount;
6576 HWND window;
6577 HRESULT hr;
6579 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6580 0, 0, 640, 480, 0, 0, 0, 0);
6581 ddraw = create_ddraw();
6582 ok(!!ddraw, "Failed to create a ddraw object.\n");
6583 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6584 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6586 memset(&surface_desc, 0, sizeof(surface_desc));
6587 surface_desc.dwSize = sizeof(surface_desc);
6588 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6589 surface_desc.dwWidth = 16;
6590 surface_desc.dwHeight = 16;
6591 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6592 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6593 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6595 memset(&surface_desc, 0xaa, sizeof(surface_desc));
6596 surface_desc.dwSize = sizeof(surface_desc);
6597 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
6598 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6599 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
6601 memset(&surface_desc, 0xaa, sizeof(surface_desc));
6602 surface_desc.dwSize = sizeof(surface_desc);
6603 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, 0, NULL);
6604 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6605 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
6606 memset(&surface_desc, 0xaa, sizeof(surface_desc));
6607 surface_desc.dwSize = sizeof(surface_desc);
6608 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
6609 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6610 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
6611 hr = IDirectDrawSurface_Unlock(surface, NULL);
6612 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6614 memset(&surface_desc, 0xaa, sizeof(surface_desc));
6615 surface_desc.dwSize = sizeof(surface_desc);
6616 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
6617 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6618 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
6620 IDirectDrawSurface_Release(surface);
6621 refcount = IDirectDraw_Release(ddraw);
6622 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6623 DestroyWindow(window);
6626 static void test_texturemapblend(void)
6628 HRESULT hr;
6629 DDSURFACEDESC ddsd;
6630 D3DEXECUTEBUFFERDESC exec_desc;
6631 DDBLTFX fx;
6632 static RECT rect = {0, 0, 64, 128};
6633 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
6634 DDCOLORKEY ckey;
6635 IDirectDrawSurface *surface, *rt;
6636 IDirect3DTexture *texture;
6637 D3DTEXTUREHANDLE texture_handle;
6638 HWND window;
6639 IDirectDraw *ddraw;
6640 IDirect3DDevice *device;
6641 IDirect3DMaterial *material;
6642 IDirect3DViewport *viewport;
6643 IDirect3DExecuteBuffer *execute_buffer;
6644 UINT inst_length;
6645 void *ptr;
6646 ULONG ref;
6647 D3DCOLOR color;
6649 static const D3DTLVERTEX test1_quads[] =
6651 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {0.0f}},
6652 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {1.0f}},
6653 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {0.0f}},
6654 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {1.0f}},
6655 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {0.0f}},
6656 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {1.0f}},
6657 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {0.0f}},
6658 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {1.0f}},
6660 test2_quads[] =
6662 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {0.0f}},
6663 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {1.0f}},
6664 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {0.0f}},
6665 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {1.0f}},
6666 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {0.0f}},
6667 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {1.0f}},
6668 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {0.0f}},
6669 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {1.0f}},
6672 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6673 0, 0, 640, 480, 0, 0, 0, 0);
6674 ddraw = create_ddraw();
6675 ok(!!ddraw, "Failed to create a ddraw object.\n");
6676 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
6678 skip("Failed to create a 3D device, skipping test.\n");
6679 DestroyWindow(window);
6680 IDirectDraw_Release(ddraw);
6681 return;
6684 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
6685 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
6687 material = create_diffuse_material(device, 0.0f, 0.0f, 0.0f, 1.0f);
6688 viewport = create_viewport(device, 0, 0, 640, 480);
6689 viewport_set_background(device, viewport, material);
6691 memset(&exec_desc, 0, sizeof(exec_desc));
6692 exec_desc.dwSize = sizeof(exec_desc);
6693 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
6694 exec_desc.dwBufferSize = 1024;
6695 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
6696 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
6697 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
6699 /* Test alpha with DDPF_ALPHAPIXELS texture - should be taken from texture alpha channel.
6701 * The vertex alpha is completely ignored in this case, so case 1 and 2 combined are not
6702 * a D3DTOP_MODULATE with texture alpha = 0xff in case 2 (no alpha in texture). */
6703 memset(&ddsd, 0, sizeof(ddsd));
6704 ddsd.dwSize = sizeof(ddsd);
6705 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
6706 ddsd.dwHeight = 128;
6707 ddsd.dwWidth = 128;
6708 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6709 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
6710 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
6711 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
6712 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6713 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6714 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6715 U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
6716 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
6717 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6719 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
6720 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
6721 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
6722 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
6724 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6725 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
6727 memset(&fx, 0, sizeof(fx));
6728 fx.dwSize = sizeof(fx);
6729 U5(fx).dwFillColor = 0xff0000ff;
6730 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6731 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
6732 U5(fx).dwFillColor = 0x800000ff;
6733 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6734 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
6736 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
6737 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
6739 memcpy(exec_desc.lpData, test1_quads, sizeof(test1_quads));
6741 ptr = ((BYTE *)exec_desc.lpData) + sizeof(test1_quads);
6742 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
6743 emit_set_rs(&ptr, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
6744 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
6745 emit_set_rs(&ptr, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
6746 emit_set_rs(&ptr, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
6747 /* The history of D3DRENDERSTATE_ALPHABLENDENABLE is quite a mess. In the
6748 * first D3D release there was a D3DRENDERSTATE_BLENDENABLE (enum value 27).
6749 * D3D5 introduced a new and separate D3DRENDERSTATE_ALPHABLENDENABLE (42)
6750 * together with D3DRENDERSTATE_COLORKEYENABLE (41). The docs aren't all
6751 * that clear but they mention that D3DRENDERSTATE_BLENDENABLE overrides the
6752 * two new states.
6753 * Then D3D6 came and got rid of the new D3DRENDERSTATE_ALPHABLENDENABLE
6754 * state (42), renaming the older D3DRENDERSTATE_BLENDENABLE enum (27)
6755 * as D3DRENDERSTATE_ALPHABLENDENABLE.
6756 * There is a comment in the D3D6 docs which mentions that hardware
6757 * rasterizers always used D3DRENDERSTATE_BLENDENABLE to just toggle alpha
6758 * blending while prior to D3D5 software rasterizers toggled both color
6759 * keying and alpha blending according to it. What I gather is that, from
6760 * D3D6 onwards, D3DRENDERSTATE_ALPHABLENDENABLE always only toggles the
6761 * alpha blending state.
6762 * These tests seem to show that actual, current hardware follows the D3D6
6763 * behavior even when using the original D3D interfaces, for the HAL device
6764 * at least. */
6765 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
6766 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
6767 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
6769 emit_tquad(&ptr, 0);
6770 emit_tquad(&ptr, 4);
6771 emit_end(&ptr);
6773 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
6774 inst_length -= sizeof(test1_quads);
6775 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
6776 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
6777 set_execute_data(execute_buffer, 8, sizeof(test1_quads), inst_length);
6779 hr = IDirect3DDevice_BeginScene(device);
6780 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6781 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
6782 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
6783 hr = IDirect3DDevice_EndScene(device);
6784 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6786 color = get_surface_color(rt, 5, 5);
6787 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
6788 color = get_surface_color(rt, 400, 5);
6789 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
6790 color = get_surface_color(rt, 5, 245);
6791 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
6792 color = get_surface_color(rt, 400, 245);
6793 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
6795 IDirect3DTexture_Release(texture);
6796 ref = IDirectDrawSurface_Release(surface);
6797 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
6799 /* Test alpha with texture that has no alpha channel - alpha should be taken from diffuse vertex color. */
6800 memset(&ddsd, 0, sizeof(ddsd));
6801 ddsd.dwSize = sizeof(ddsd);
6802 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
6803 ddsd.dwHeight = 128;
6804 ddsd.dwWidth = 128;
6805 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6806 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
6807 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
6808 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
6809 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6810 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6811 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6813 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
6814 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6816 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
6817 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
6818 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
6819 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
6821 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6822 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
6824 U5(fx).dwFillColor = 0xff0000ff;
6825 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6826 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
6827 U5(fx).dwFillColor = 0x800000ff;
6828 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6829 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
6831 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
6832 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
6834 ptr = ((BYTE *)exec_desc.lpData) + sizeof(test1_quads);
6835 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
6836 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
6838 emit_tquad(&ptr, 0);
6839 emit_tquad(&ptr, 4);
6840 emit_end(&ptr);
6842 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
6843 inst_length -= sizeof(test1_quads);
6844 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
6845 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
6846 set_execute_data(execute_buffer, 8, sizeof(test1_quads), inst_length);
6848 hr = IDirect3DDevice_BeginScene(device);
6849 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6850 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
6851 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
6852 hr = IDirect3DDevice_EndScene(device);
6853 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6855 color = get_surface_color(rt, 5, 5);
6856 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
6857 color = get_surface_color(rt, 400, 5);
6858 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
6859 color = get_surface_color(rt, 5, 245);
6860 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
6861 color = get_surface_color(rt, 400, 245);
6862 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
6864 IDirect3DTexture_Release(texture);
6865 ref = IDirectDrawSurface_Release(surface);
6866 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
6868 /* Test RGB - should multiply color components from diffuse vertex color and texture. */
6869 memset(&ddsd, 0, sizeof(ddsd));
6870 ddsd.dwSize = sizeof(ddsd);
6871 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
6872 ddsd.dwHeight = 128;
6873 ddsd.dwWidth = 128;
6874 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6875 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
6876 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
6877 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
6878 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6879 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6880 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6881 U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
6882 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
6883 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6885 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
6886 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
6887 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
6888 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
6890 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6891 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
6893 U5(fx).dwFillColor = 0x00ffffff;
6894 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6895 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
6896 U5(fx).dwFillColor = 0x00ffff80;
6897 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6898 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
6900 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
6901 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
6903 memcpy(exec_desc.lpData, test2_quads, sizeof(test2_quads));
6905 ptr = ((BYTE *)exec_desc.lpData) + sizeof(test2_quads);
6906 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
6907 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
6908 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
6910 emit_tquad(&ptr, 0);
6911 emit_tquad(&ptr, 4);
6912 emit_end(&ptr);
6914 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
6915 inst_length -= sizeof(test2_quads);
6916 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
6917 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
6918 set_execute_data(execute_buffer, 8, sizeof(test2_quads), inst_length);
6920 hr = IDirect3DDevice_BeginScene(device);
6921 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6922 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
6923 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
6924 hr = IDirect3DDevice_EndScene(device);
6925 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6927 /* WARP (Win8 testbot) emulates color keying with the alpha channel like Wine does,
6928 * but even applies it when there's no color key assigned. The surface alpha is zero
6929 * here, so nothing gets drawn.
6931 * The ddraw2 version of this test draws these quads with color keying off due to
6932 * different defaults in ddraw1 and ddraw2. */
6933 color = get_surface_color(rt, 5, 5);
6934 ok(compare_color(color, 0x00ff0040, 2) || broken(compare_color(color, 0x00000000, 1)),
6935 "Got unexpected color 0x%08x.\n", color);
6936 color = get_surface_color(rt, 400, 5);
6937 ok(compare_color(color, 0x00ff0080, 2) || broken(compare_color(color, 0x00000000, 1)),
6938 "Got unexpected color 0x%08x.\n", color);
6939 color = get_surface_color(rt, 5, 245);
6940 ok(compare_color(color, 0x00800080, 2) || broken(compare_color(color, 0x00000000, 1)),
6941 "Got unexpected color 0x%08x.\n", color);
6942 color = get_surface_color(rt, 400, 245);
6943 ok(compare_color(color, 0x008000ff, 2) || broken(compare_color(color, 0x00000000, 1)),
6944 "Got unexpected color 0x%08x.\n", color);
6946 IDirect3DTexture_Release(texture);
6947 ref = IDirectDrawSurface_Release(surface);
6948 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
6950 /* Test alpha again, now with color keyed texture (colorkey emulation in wine can interfere). */
6951 memset(&ddsd, 0, sizeof(ddsd));
6952 ddsd.dwSize = sizeof(ddsd);
6953 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
6954 ddsd.dwHeight = 128;
6955 ddsd.dwWidth = 128;
6956 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6957 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
6958 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
6959 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 16;
6960 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xf800;
6961 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x07e0;
6962 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x001f;
6964 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
6965 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6967 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
6968 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
6969 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
6970 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
6972 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6973 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
6975 U5(fx).dwFillColor = 0xf800;
6976 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6977 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
6978 U5(fx).dwFillColor = 0x001f;
6979 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6980 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
6982 ckey.dwColorSpaceLowValue = 0x001f;
6983 ckey.dwColorSpaceHighValue = 0x001f;
6984 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
6985 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
6987 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
6988 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
6990 memcpy(exec_desc.lpData, test1_quads, sizeof(test1_quads));
6992 ptr = ((BYTE *)exec_desc.lpData) + sizeof(test1_quads);
6993 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
6994 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
6995 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
6996 /* D3DRENDERSTATE_COLORKEYENABLE is supposed to be on by default on version
6997 * 1 devices, but for some reason it randomly defaults to FALSE on the W8
6998 * testbot. This is either the fault of Windows 8 or the WARP driver.
6999 * Also D3DRENDERSTATE_COLORKEYENABLE was introduced in D3D 5 aka version 2
7000 * devices only, which might imply this doesn't actually do anything on
7001 * WARP. */
7002 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
7004 emit_tquad(&ptr, 0);
7005 emit_tquad(&ptr, 4);
7006 emit_end(&ptr);
7008 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
7009 inst_length -= sizeof(test1_quads);
7010 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
7011 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
7012 set_execute_data(execute_buffer, 8, sizeof(test1_quads), inst_length);
7014 hr = IDirect3DDevice_BeginScene(device);
7015 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7016 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
7017 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
7018 hr = IDirect3DDevice_EndScene(device);
7019 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7021 /* Allow broken WARP results (colorkey disabled). */
7022 color = get_surface_color(rt, 5, 5);
7023 ok(compare_color(color, 0x00000000, 2) || broken(compare_color(color, 0x000000ff, 2)),
7024 "Got unexpected color 0x%08x.\n", color);
7025 color = get_surface_color(rt, 400, 5);
7026 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
7027 color = get_surface_color(rt, 5, 245);
7028 ok(compare_color(color, 0x00000000, 2) || broken(compare_color(color, 0x00000080, 2)),
7029 "Got unexpected color 0x%08x.\n", color);
7030 color = get_surface_color(rt, 400, 245);
7031 ok(compare_color(color, 0x00800000, 2), "Got unexpected color 0x%08x.\n", color);
7033 IDirect3DTexture_Release(texture);
7034 ref = IDirectDrawSurface_Release(surface);
7035 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
7037 ref = IDirect3DExecuteBuffer_Release(execute_buffer);
7038 ok(ref == 0, "Execute buffer not properly released, refcount %u.\n", ref);
7039 destroy_viewport(device, viewport);
7040 ref = IDirect3DMaterial_Release(material);
7041 ok(ref == 0, "Material not properly released, refcount %u.\n", ref);
7042 IDirectDrawSurface_Release(rt);
7043 IDirect3DDevice_Release(device);
7044 ref = IDirectDraw_Release(ddraw);
7045 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7046 DestroyWindow(window);
7049 static void test_viewport_clear_rect(void)
7051 HRESULT hr;
7052 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
7053 static D3DRECT clear_rect2 = {{90}, {90}, {110}, {110}};
7054 IDirectDrawSurface *rt;
7055 HWND window;
7056 IDirectDraw *ddraw;
7057 IDirect3DDevice *device;
7058 IDirect3DMaterial *red, *green;
7059 IDirect3DViewport *viewport, *viewport2;
7060 ULONG ref;
7061 D3DCOLOR color;
7063 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7064 0, 0, 640, 480, 0, 0, 0, 0);
7065 ddraw = create_ddraw();
7066 ok(!!ddraw, "Failed to create a ddraw object.\n");
7067 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7069 skip("Failed to create a 3D device, skipping test.\n");
7070 DestroyWindow(window);
7071 IDirectDraw_Release(ddraw);
7072 return;
7075 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
7076 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
7078 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
7079 viewport = create_viewport(device, 0, 0, 640, 480);
7080 viewport_set_background(device, viewport, red);
7081 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7082 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7084 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
7085 viewport2 = create_viewport(device, 100, 100, 20, 20);
7086 viewport_set_background(device, viewport2, green);
7087 hr = IDirect3DViewport_Clear(viewport2, 1, &clear_rect2, D3DCLEAR_TARGET);
7088 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7090 color = get_surface_color(rt, 85, 85); /* Outside both. */
7091 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
7092 color = get_surface_color(rt, 95, 95); /* Outside vp, inside rect. */
7093 /* AMD GPUs ignore the viewport dimensions and only care about the rectangle. */
7094 ok(compare_color(color, 0x00ff0000, 1) || broken(compare_color(color, 0x0000ff00, 1)),
7095 "Got unexpected color 0x%08x.\n", color);
7096 color = get_surface_color(rt, 105, 105); /* Inside both. */
7097 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
7098 color = get_surface_color(rt, 115, 115); /* Inside vp, outside rect. */
7099 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
7100 color = get_surface_color(rt, 125, 125); /* Outside both. */
7101 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
7103 destroy_viewport(device, viewport2);
7104 destroy_material(green);
7105 destroy_viewport(device, viewport);
7106 destroy_material(red);
7107 IDirectDrawSurface_Release(rt);
7108 IDirect3DDevice_Release(device);
7109 ref = IDirectDraw_Release(ddraw);
7110 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7111 DestroyWindow(window);
7114 static void test_color_fill(void)
7116 HRESULT hr;
7117 IDirect3DDevice *device;
7118 IDirectDraw *ddraw;
7119 IDirectDrawSurface *surface, *surface2;
7120 DDSURFACEDESC surface_desc;
7121 ULONG refcount;
7122 HWND window;
7123 unsigned int i;
7124 DDBLTFX fx;
7125 RECT rect = {5, 5, 7, 7};
7126 DWORD *color;
7127 DWORD num_fourcc_codes, *fourcc_codes;
7128 DDCAPS hal_caps;
7129 BOOL support_uyvy = FALSE, support_yuy2 = FALSE;
7130 static const struct
7132 DWORD caps;
7133 HRESULT colorfill_hr, depthfill_hr;
7134 BOOL rop_success;
7135 const char *name;
7136 DWORD result;
7137 BOOL check_result;
7138 DDPIXELFORMAT format;
7140 tests[] =
7143 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
7144 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
7146 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
7147 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
7151 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
7152 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
7154 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
7155 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
7159 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
7160 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
7162 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
7163 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
7167 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
7168 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
7170 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
7171 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
7175 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY,
7176 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0, FALSE,
7177 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
7180 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
7181 * different afterwards. DX9+ GPUs set one of the two luminance values
7182 * in each block, but AMD and Nvidia GPUs disagree on which luminance
7183 * value they set. r200 (dx8) just sets the entire block to the clear
7184 * value. */
7185 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
7186 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
7188 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
7189 {0}, {0}, {0}, {0}, {0}
7193 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
7194 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
7196 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
7197 {0}, {0}, {0}, {0}, {0}
7201 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
7202 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
7204 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
7205 {0}, {0}, {0}, {0}, {0}
7209 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
7210 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
7212 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
7213 {0}, {0}, {0}, {0}, {0}
7217 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
7218 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
7220 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
7221 {0}, {0}, {0}, {0}, {0}
7225 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
7226 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
7228 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
7229 {0}, {0}, {0}, {0}, {0}
7233 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
7234 * surface works, presumably because it is handled by the runtime instead of
7235 * the driver. */
7236 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
7237 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
7239 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
7240 {8}, {0}, {0}, {0}, {0}
7244 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
7245 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
7247 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
7248 {8}, {0}, {0}, {0}, {0}
7252 static const struct
7254 DWORD rop;
7255 const char *name;
7256 HRESULT hr;
7258 rops[] =
7260 {SRCCOPY, "SRCCOPY", DD_OK},
7261 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
7262 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
7263 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
7264 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
7265 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
7266 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
7267 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
7268 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
7269 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
7270 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
7271 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
7272 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
7273 {BLACKNESS, "BLACKNESS", DD_OK},
7274 {WHITENESS, "WHITENESS", DD_OK},
7275 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
7278 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7279 0, 0, 640, 480, 0, 0, 0, 0);
7280 ddraw = create_ddraw();
7281 ok(!!ddraw, "Failed to create a ddraw object.\n");
7282 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7284 skip("Failed to create a 3D device, skipping test.\n");
7285 DestroyWindow(window);
7286 IDirectDraw_Release(ddraw);
7287 return;
7290 hr = IDirectDraw_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
7291 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
7292 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7293 num_fourcc_codes * sizeof(*fourcc_codes));
7294 if (!fourcc_codes)
7295 goto done;
7296 hr = IDirectDraw_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
7297 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
7298 for (i = 0; i < num_fourcc_codes; i++)
7300 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
7301 support_yuy2 = TRUE;
7302 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
7303 support_uyvy = TRUE;
7305 HeapFree(GetProcessHeap(), 0, fourcc_codes);
7307 memset(&hal_caps, 0, sizeof(hal_caps));
7308 hal_caps.dwSize = sizeof(hal_caps);
7309 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
7310 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7312 if ((!support_yuy2 && !support_uyvy) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
7313 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
7315 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
7317 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
7318 memset(&fx, 0, sizeof(fx));
7319 fx.dwSize = sizeof(fx);
7320 U5(fx).dwFillColor = 0xdeadbeef;
7322 memset(&surface_desc, 0, sizeof(surface_desc));
7323 surface_desc.dwSize = sizeof(surface_desc);
7324 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7325 surface_desc.dwWidth = 64;
7326 surface_desc.dwHeight = 64;
7327 surface_desc.ddpfPixelFormat = tests[i].format;
7328 surface_desc.ddsCaps.dwCaps = tests[i].caps;
7330 if (tests[i].caps & DDSCAPS_TEXTURE)
7332 struct format_support_check check = {&tests[i].format, FALSE};
7333 hr = IDirect3DDevice_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
7334 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
7335 if (!check.supported)
7336 continue;
7339 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !support_yuy2)
7340 continue;
7341 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !support_uyvy)
7342 continue;
7343 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
7344 continue;
7346 if (tests[i].caps & DDSCAPS_ZBUFFER)
7348 surface_desc.dwFlags &= ~DDSD_PIXELFORMAT;
7349 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
7350 U2(surface_desc).dwZBufferBitDepth = get_device_z_depth(device);
7353 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7354 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
7356 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7357 todo_wine_if (tests[i].format.dwFourCC)
7358 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
7359 hr, tests[i].colorfill_hr, tests[i].name);
7361 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7362 todo_wine_if (tests[i].format.dwFourCC)
7363 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
7364 hr, tests[i].colorfill_hr, tests[i].name);
7366 if (SUCCEEDED(hr) && tests[i].check_result)
7368 memset(&surface_desc, 0, sizeof(surface_desc));
7369 surface_desc.dwSize = sizeof(surface_desc);
7370 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
7371 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
7372 color = surface_desc.lpSurface;
7373 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
7374 *color, tests[i].result, tests[i].name);
7375 hr = IDirectDrawSurface_Unlock(surface, NULL);
7376 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
7379 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7380 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
7381 hr, tests[i].depthfill_hr, tests[i].name);
7382 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7383 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
7384 hr, tests[i].depthfill_hr, tests[i].name);
7386 U5(fx).dwFillColor = 0xdeadbeef;
7387 fx.dwROP = BLACKNESS;
7388 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
7389 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
7390 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
7391 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
7392 U5(fx).dwFillColor, tests[i].name);
7394 if (SUCCEEDED(hr) && tests[i].check_result)
7396 memset(&surface_desc, 0, sizeof(surface_desc));
7397 surface_desc.dwSize = sizeof(surface_desc);
7398 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
7399 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
7400 color = surface_desc.lpSurface;
7401 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
7402 *color, tests[i].name);
7403 hr = IDirectDrawSurface_Unlock(surface, NULL);
7404 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
7407 fx.dwROP = WHITENESS;
7408 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
7409 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
7410 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
7411 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
7412 U5(fx).dwFillColor, tests[i].name);
7414 if (SUCCEEDED(hr) && tests[i].check_result)
7416 memset(&surface_desc, 0, sizeof(surface_desc));
7417 surface_desc.dwSize = sizeof(surface_desc);
7418 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
7419 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
7420 color = surface_desc.lpSurface;
7421 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
7422 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
7423 *color, tests[i].name);
7424 hr = IDirectDrawSurface_Unlock(surface, NULL);
7425 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
7428 IDirectDrawSurface_Release(surface);
7431 memset(&fx, 0, sizeof(fx));
7432 fx.dwSize = sizeof(fx);
7433 U5(fx).dwFillColor = 0xdeadbeef;
7434 fx.dwROP = WHITENESS;
7436 memset(&surface_desc, 0, sizeof(surface_desc));
7437 surface_desc.dwSize = sizeof(surface_desc);
7438 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7439 surface_desc.dwWidth = 64;
7440 surface_desc.dwHeight = 64;
7441 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7442 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
7443 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
7444 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7445 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7446 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
7447 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
7448 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7449 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7450 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7451 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7453 /* No DDBLTFX. */
7454 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
7455 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7456 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
7457 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7459 /* Unused source rectangle. */
7460 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7461 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7462 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
7463 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7465 /* Unused source surface. */
7466 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7467 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7468 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
7469 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7470 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7471 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7472 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
7473 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7475 /* Inverted destination or source rectangle. */
7476 SetRect(&rect, 5, 7, 7, 5);
7477 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7478 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7479 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7480 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7481 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7482 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7483 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7484 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7485 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
7486 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7488 /* Negative rectangle. */
7489 SetRect(&rect, -1, -1, 5, 5);
7490 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7491 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7492 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7493 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7494 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7495 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7496 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7497 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7498 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
7499 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7501 /* Out of bounds rectangle. */
7502 SetRect(&rect, 0, 0, 65, 65);
7503 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7504 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7505 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
7506 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7508 /* Combine multiple flags. */
7509 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7510 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7511 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
7512 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7513 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
7514 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7516 for (i = 0; i < sizeof(rops) / sizeof(*rops); i++)
7518 fx.dwROP = rops[i].rop;
7519 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
7520 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
7523 IDirectDrawSurface_Release(surface2);
7524 IDirectDrawSurface_Release(surface);
7526 memset(&surface_desc, 0, sizeof(surface_desc));
7527 surface_desc.dwSize = sizeof(surface_desc);
7528 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
7529 surface_desc.dwWidth = 64;
7530 surface_desc.dwHeight = 64;
7531 U2(surface_desc).dwZBufferBitDepth = get_device_z_depth(device);
7532 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7533 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7534 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7535 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7536 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7538 /* No DDBLTFX. */
7539 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
7540 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7542 /* Unused source rectangle. */
7543 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7544 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7546 /* Unused source surface. */
7547 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7548 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7549 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7550 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7552 /* Inverted destination or source rectangle. */
7553 SetRect(&rect, 5, 7, 7, 5);
7554 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7555 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7556 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7557 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7558 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7559 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7560 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7561 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7563 /* Negative rectangle. */
7564 SetRect(&rect, -1, -1, 5, 5);
7565 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7566 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7567 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7568 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
7569 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7570 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7571 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7572 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7574 /* Out of bounds rectangle. */
7575 SetRect(&rect, 0, 0, 65, 65);
7576 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7577 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
7579 /* Combine multiple flags. */
7580 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
7581 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7583 IDirectDrawSurface_Release(surface2);
7584 IDirectDrawSurface_Release(surface);
7586 done:
7587 IDirect3DDevice_Release(device);
7588 refcount = IDirectDraw_Release(ddraw);
7589 ok(refcount == 0, "Ddraw object not properly released, refcount %u.\n", refcount);
7590 DestroyWindow(window);
7593 static BOOL ddraw_is_nvidia(IDirectDraw *ddraw)
7595 IDirectDraw4 *ddraw4;
7596 DDDEVICEIDENTIFIER identifier;
7597 HRESULT hr;
7599 if (!strcmp(winetest_platform, "wine"))
7600 return FALSE;
7602 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw4, (void **)&ddraw4);
7603 ok(SUCCEEDED(hr), "Failed to get IDirectDraw4 interface, hr %#x.\n", hr);
7604 hr = IDirectDraw4_GetDeviceIdentifier(ddraw4, &identifier, 0);
7605 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
7606 IDirectDraw4_Release(ddraw4);
7607 return identifier.dwVendorId == 0x10de;
7610 static void test_colorkey_precision(void)
7612 static D3DTLVERTEX quad[] =
7614 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {0.0f}, {1.0f}},
7615 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {0.0f}, {0.0f}},
7616 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {1.0f}, {1.0f}},
7617 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {1.0f}, {0.0f}},
7619 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
7620 IDirect3DDevice *device;
7621 IDirectDraw *ddraw;
7622 IDirectDrawSurface *rt;
7623 IDirect3DViewport *viewport;
7624 IDirect3DExecuteBuffer *execute_buffer;
7625 D3DEXECUTEBUFFERDESC exec_desc;
7626 UINT inst_length;
7627 void *ptr;
7628 HWND window;
7629 HRESULT hr;
7630 IDirectDrawSurface *src, *dst, *texture;
7631 D3DTEXTUREHANDLE handle;
7632 IDirect3DTexture *d3d_texture;
7633 IDirect3DMaterial *green;
7634 DDSURFACEDESC surface_desc, lock_desc;
7635 ULONG refcount;
7636 D3DCOLOR color;
7637 unsigned int t, c;
7638 DDCOLORKEY ckey;
7639 DDBLTFX fx;
7640 DWORD data[4] = {0}, color_mask;
7641 BOOL is_nvidia, is_warp;
7642 static const struct
7644 unsigned int max, shift, bpp, clear;
7645 const char *name;
7646 BOOL skip_nv;
7647 DDPIXELFORMAT fmt;
7649 tests[] =
7652 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
7654 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
7655 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
7660 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
7662 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
7663 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
7668 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
7670 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
7671 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
7676 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
7678 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
7679 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
7684 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7685 0, 0, 640, 480, 0, 0, 0, 0);
7686 ddraw = create_ddraw();
7687 ok(!!ddraw, "Failed to create a ddraw object.\n");
7688 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7690 skip("Failed to create a 3D device, skipping test.\n");
7691 DestroyWindow(window);
7692 IDirectDraw_Release(ddraw);
7693 return;
7695 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
7696 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
7698 is_nvidia = ddraw_is_nvidia(ddraw);
7699 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
7700 * (color key doesn't match although the values are equal), and a false
7701 * positive when the color key is 0 and the texture contains the value 1.
7702 * I don't want to mark this broken unconditionally since this would
7703 * essentially disable the test on Windows. Also on random occasions
7704 * 254 == 255 and 255 != 255.*/
7705 is_warp = ddraw_is_warp(ddraw);
7707 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
7708 viewport = create_viewport(device, 0, 0, 640, 480);
7709 viewport_set_background(device, viewport, green);
7711 memset(&exec_desc, 0, sizeof(exec_desc));
7712 exec_desc.dwSize = sizeof(exec_desc);
7713 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
7714 exec_desc.dwBufferSize = 1024;
7715 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
7716 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
7717 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
7719 memset(&fx, 0, sizeof(fx));
7720 fx.dwSize = sizeof(fx);
7721 memset(&lock_desc, 0, sizeof(lock_desc));
7722 lock_desc.dwSize = sizeof(lock_desc);
7724 for (t = 0; t < sizeof(tests) / sizeof(*tests); ++t)
7726 if (is_nvidia && tests[t].skip_nv)
7728 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
7729 continue;
7732 memset(&surface_desc, 0, sizeof(surface_desc));
7733 surface_desc.dwSize = sizeof(surface_desc);
7734 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7735 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7736 surface_desc.dwWidth = 4;
7737 surface_desc.dwHeight = 1;
7738 surface_desc.ddpfPixelFormat = tests[t].fmt;
7739 /* Windows XP (at least with the r200 driver, other drivers untested) produces
7740 * garbage when doing color keyed texture->texture blits. */
7741 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src, NULL);
7742 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7743 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst, NULL);
7744 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7746 fx.dwFillColor = tests[t].clear;
7747 /* On the w8 testbot (WARP driver) the blit result has different values in the
7748 * X channel. */
7749 color_mask = U2(tests[t].fmt).dwRBitMask
7750 | U3(tests[t].fmt).dwGBitMask
7751 | U4(tests[t].fmt).dwBBitMask;
7753 for (c = 0; c <= tests[t].max; ++c)
7755 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
7756 * texture after it has been set once... */
7757 surface_desc.dwFlags |= DDSD_CKSRCBLT;
7758 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7759 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
7760 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
7761 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &texture, NULL);
7762 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7764 hr = IDirectDrawSurface_QueryInterface(texture, &IID_IDirect3DTexture, (void **)&d3d_texture);
7765 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
7766 hr = IDirect3DTexture_GetHandle(d3d_texture, device, &handle);
7767 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
7768 IDirect3DTexture_Release(d3d_texture);
7770 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
7771 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
7773 memcpy(exec_desc.lpData, quad, sizeof(quad));
7775 ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad);
7776 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
7777 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
7778 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, handle);
7779 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATEALPHA);
7780 /* D3DRENDERSTATE_COLORKEYENABLE is supposed to be on by default on version
7781 * 1 devices, but for some reason it randomly defaults to FALSE on the W8
7782 * testbot. This is either the fault of Windows 8 or the WARP driver.
7783 * Also D3DRENDERSTATE_COLORKEYENABLE was introduced in D3D 5 aka version 2
7784 * devices only, which might imply this doesn't actually do anything on
7785 * WARP. */
7786 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
7788 emit_tquad(&ptr, 0);
7789 emit_tquad(&ptr, 4);
7790 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
7791 emit_end(&ptr);
7793 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
7794 inst_length -= sizeof(quad);
7795 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
7796 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
7797 set_execute_data(execute_buffer, 8, sizeof(quad), inst_length);
7799 hr = IDirectDrawSurface_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7800 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
7802 hr = IDirectDrawSurface_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
7803 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7804 switch (tests[t].bpp)
7806 case 4:
7807 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
7808 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
7809 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
7810 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
7811 break;
7813 case 2:
7814 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
7815 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
7816 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
7817 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
7818 break;
7820 hr = IDirectDrawSurface_Unlock(src, 0);
7821 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7822 hr = IDirectDrawSurface_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
7823 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
7825 ckey.dwColorSpaceLowValue = c << tests[t].shift;
7826 ckey.dwColorSpaceHighValue = c << tests[t].shift;
7827 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
7828 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
7830 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
7831 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
7833 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
7834 hr = IDirectDrawSurface_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
7835 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7836 switch (tests[t].bpp)
7838 case 4:
7839 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
7840 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
7841 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
7842 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
7843 break;
7845 case 2:
7846 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
7847 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
7848 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
7849 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
7850 break;
7852 hr = IDirectDrawSurface_Unlock(dst, 0);
7853 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7855 if (!c)
7857 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
7858 tests[t].clear, data[0], tests[t].name, c);
7860 if (data[3] == tests[t].clear)
7862 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
7863 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
7864 * even when a different surface is used. The blit itself doesn't draw anything,
7865 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
7866 * never be masked out by the key.
7868 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
7869 * test is disabled entirely.
7871 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
7872 * terrible on WARP. */
7873 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
7874 IDirectDrawSurface_Release(texture);
7875 IDirectDrawSurface_Release(src);
7876 IDirectDrawSurface_Release(dst);
7877 goto done;
7880 else
7881 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
7882 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
7884 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
7885 tests[t].clear, data[1], tests[t].name, c);
7887 if (c == tests[t].max)
7888 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
7889 tests[t].clear, data[2], tests[t].name, c);
7890 else
7891 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
7892 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
7894 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7895 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
7897 hr = IDirect3DDevice_BeginScene(device);
7898 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7899 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
7900 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7901 hr = IDirect3DDevice_EndScene(device);
7902 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7904 color = get_surface_color(rt, 80, 240);
7905 if (!c)
7906 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
7907 "Got unexpected color 0x%08x, format %s, c=%u.\n",
7908 color, tests[t].name, c);
7909 else
7910 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
7911 "Got unexpected color 0x%08x, format %s, c=%u.\n",
7912 color, tests[t].name, c);
7914 color = get_surface_color(rt, 240, 240);
7915 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
7916 "Got unexpected color 0x%08x, format %s, c=%u.\n",
7917 color, tests[t].name, c);
7919 color = get_surface_color(rt, 400, 240);
7920 if (c == tests[t].max)
7921 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
7922 "Got unexpected color 0x%08x, format %s, c=%u.\n",
7923 color, tests[t].name, c);
7924 else
7925 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
7926 "Got unexpected color 0x%08x, format %s, c=%u.\n",
7927 color, tests[t].name, c);
7929 IDirectDrawSurface_Release(texture);
7931 IDirectDrawSurface_Release(src);
7932 IDirectDrawSurface_Release(dst);
7934 done:
7936 destroy_viewport(device, viewport);
7937 destroy_material(green);
7938 IDirectDrawSurface_Release(rt);
7939 IDirect3DExecuteBuffer_Release(execute_buffer);
7940 IDirect3DDevice_Release(device);
7941 refcount = IDirectDraw_Release(ddraw);
7942 ok(refcount == 0, "Ddraw object not properly released, refcount %u.\n", refcount);
7943 DestroyWindow(window);
7946 static void test_range_colorkey(void)
7948 IDirectDraw *ddraw;
7949 HWND window;
7950 HRESULT hr;
7951 IDirectDrawSurface *surface;
7952 DDSURFACEDESC surface_desc;
7953 ULONG refcount;
7954 DDCOLORKEY ckey;
7956 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7957 0, 0, 640, 480, 0, 0, 0, 0);
7958 ddraw = create_ddraw();
7959 ok(!!ddraw, "Failed to create a ddraw object.\n");
7960 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7961 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7963 memset(&surface_desc, 0, sizeof(surface_desc));
7964 surface_desc.dwSize = sizeof(surface_desc);
7965 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
7966 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7967 surface_desc.dwWidth = 1;
7968 surface_desc.dwHeight = 1;
7969 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
7970 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
7971 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7972 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7973 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
7974 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
7976 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
7977 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
7978 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
7979 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7980 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
7982 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
7983 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
7984 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7985 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
7987 /* Same for DDSCAPS_OFFSCREENPLAIN. */
7988 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7989 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
7990 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
7991 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7992 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
7994 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
7995 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
7996 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7997 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
7999 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
8000 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
8001 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8002 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8004 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
8005 ckey.dwColorSpaceLowValue = 0x00000000;
8006 ckey.dwColorSpaceHighValue = 0x00000001;
8007 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
8008 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
8010 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
8011 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
8012 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
8013 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
8015 ckey.dwColorSpaceLowValue = 0x00000001;
8016 ckey.dwColorSpaceHighValue = 0x00000000;
8017 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
8018 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
8020 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
8021 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
8022 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
8023 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
8025 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
8026 ckey.dwColorSpaceLowValue = 0x00000000;
8027 ckey.dwColorSpaceHighValue = 0x00000000;
8028 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
8029 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
8031 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
8032 ckey.dwColorSpaceLowValue = 0x00000001;
8033 ckey.dwColorSpaceHighValue = 0x00000000;
8034 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
8035 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8036 ckey.dwColorSpaceLowValue = 0x00000000;
8037 ckey.dwColorSpaceHighValue = 0x00000001;
8038 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
8039 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8040 /* Range destination keys don't work either. */
8041 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
8042 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8044 /* Just to show it's not because of A, R, and G having equal values. */
8045 ckey.dwColorSpaceLowValue = 0x00000000;
8046 ckey.dwColorSpaceHighValue = 0x01010101;
8047 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
8048 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
8050 /* None of these operations modified the key. */
8051 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
8052 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
8053 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
8054 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
8056 IDirectDrawSurface_Release(surface),
8057 refcount = IDirectDraw_Release(ddraw);
8058 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8059 DestroyWindow(window);
8062 static void test_shademode(void)
8064 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8065 IDirect3DExecuteBuffer *execute_buffer;
8066 D3DEXECUTEBUFFERDESC exec_desc;
8067 IDirect3DMaterial *background;
8068 IDirect3DViewport *viewport;
8069 IDirect3DDevice *device;
8070 IDirectDrawSurface *rt;
8071 const D3DLVERTEX *quad;
8072 DWORD color0, color1;
8073 UINT i, inst_length;
8074 IDirectDraw *ddraw;
8075 ULONG refcount;
8076 HWND window;
8077 HRESULT hr;
8078 void *ptr;
8079 static const D3DLVERTEX quad_strip[] =
8081 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
8082 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
8083 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
8084 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
8086 quad_list[] =
8088 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
8089 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
8090 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
8091 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
8093 static const struct
8095 DWORD primtype;
8096 DWORD shademode;
8097 DWORD color0, color1;
8099 tests[] =
8101 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
8102 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
8103 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
8104 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
8105 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x000000ff, 0x0000ff00},
8106 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
8109 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8110 0, 0, 640, 480, 0, 0, 0, 0);
8111 ddraw = create_ddraw();
8112 ok(!!ddraw, "Failed to create a ddraw object.\n");
8113 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8115 skip("Failed to create a 3D device, skipping test.\n");
8116 IDirectDraw_Release(ddraw);
8117 DestroyWindow(window);
8118 return;
8121 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
8122 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8124 background = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
8125 viewport = create_viewport(device, 0, 0, 640, 480);
8126 viewport_set_background(device, viewport, background);
8128 memset(&exec_desc, 0, sizeof(exec_desc));
8129 exec_desc.dwSize = sizeof(exec_desc);
8130 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
8131 exec_desc.dwBufferSize = 1024;
8132 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
8134 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
8135 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
8137 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
8138 * the color fixups we have to do for FLAT shading will be dependent on that. */
8140 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
8142 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8143 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8145 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
8146 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
8148 quad = tests[i].primtype == D3DPT_TRIANGLESTRIP ? quad_strip : quad_list;
8149 memcpy(exec_desc.lpData, quad, sizeof(quad_strip));
8150 ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad_strip);
8151 emit_set_rs(&ptr, D3DRENDERSTATE_CLIPPING, FALSE);
8152 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, FALSE);
8153 emit_set_rs(&ptr, D3DRENDERSTATE_FOGENABLE, FALSE);
8154 emit_set_rs(&ptr, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
8155 emit_set_rs(&ptr, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
8157 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
8158 if (tests[i].primtype == D3DPT_TRIANGLESTRIP)
8159 emit_tquad(&ptr, 0);
8160 else
8161 emit_tquad_tlist(&ptr, 0);
8162 emit_end(&ptr);
8163 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
8164 inst_length -= sizeof(quad_strip);
8166 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
8167 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
8169 hr = IDirect3DDevice2_BeginScene(device);
8170 set_execute_data(execute_buffer, 4, sizeof(quad_strip), inst_length);
8171 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
8172 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
8173 hr = IDirect3DDevice2_EndScene(device);
8174 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8176 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
8177 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
8179 /* For D3DSHADE_FLAT it should take the color of the first vertex of
8180 * each triangle. This requires EXT_provoking_vertex or similar
8181 * functionality being available. */
8182 /* PHONG should be the same as GOURAUD, since no hardware implements
8183 * this. */
8184 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
8185 i, color0, tests[i].color0);
8186 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
8187 i, color1, tests[i].color1);
8190 IDirect3DExecuteBuffer_Release(execute_buffer);
8191 destroy_viewport(device, viewport);
8192 destroy_material(background);
8193 IDirectDrawSurface_Release(rt);
8194 refcount = IDirect3DDevice_Release(device);
8195 ok(!refcount, "Device has %u references left.\n", refcount);
8196 IDirectDraw_Release(ddraw);
8197 DestroyWindow(window);
8200 static void test_lockrect_invalid(void)
8202 unsigned int i, r;
8203 IDirectDraw *ddraw;
8204 IDirectDrawSurface *surface;
8205 HWND window;
8206 HRESULT hr;
8207 DDSURFACEDESC surface_desc;
8208 DDCAPS hal_caps;
8209 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
8210 static RECT valid[] =
8212 {60, 60, 68, 68},
8213 {60, 60, 60, 68},
8214 {60, 60, 68, 60},
8215 {120, 60, 128, 68},
8216 {60, 120, 68, 128},
8218 static RECT invalid[] =
8220 {68, 60, 60, 68}, /* left > right */
8221 {60, 68, 68, 60}, /* top > bottom */
8222 {-8, 60, 0, 68}, /* left < surface */
8223 {60, -8, 68, 0}, /* top < surface */
8224 {-16, 60, -8, 68}, /* right < surface */
8225 {60, -16, 68, -8}, /* bottom < surface */
8226 {60, 60, 136, 68}, /* right > surface */
8227 {60, 60, 68, 136}, /* bottom > surface */
8228 {136, 60, 144, 68}, /* left > surface */
8229 {60, 136, 68, 144}, /* top > surface */
8231 static const struct
8233 DWORD caps;
8234 const char *name;
8235 HRESULT hr;
8237 resources[] =
8239 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, "sysmem offscreenplain", DDERR_INVALIDPARAMS},
8240 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, "vidmem offscreenplain", DDERR_INVALIDPARAMS},
8241 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "sysmem texture", DDERR_INVALIDPARAMS},
8242 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "vidmem texture", DDERR_INVALIDPARAMS},
8245 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8246 0, 0, 640, 480, 0, 0, 0, 0);
8247 ddraw = create_ddraw();
8248 ok(!!ddraw, "Failed to create a ddraw object.\n");
8249 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8250 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8252 memset(&hal_caps, 0, sizeof(hal_caps));
8253 hal_caps.dwSize = sizeof(hal_caps);
8254 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
8255 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8256 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
8258 skip("Required surface types not supported, skipping test.\n");
8259 goto done;
8262 for (r = 0; r < sizeof(resources) / sizeof(*resources); ++r)
8264 memset(&surface_desc, 0, sizeof(surface_desc));
8265 surface_desc.dwSize = sizeof(surface_desc);
8266 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8267 surface_desc.ddsCaps.dwCaps = resources[r].caps;
8268 surface_desc.dwWidth = 128;
8269 surface_desc.dwHeight = 128;
8270 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
8271 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
8272 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
8273 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xff0000;
8274 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x00ff00;
8275 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x0000ff;
8277 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8278 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
8280 hr = IDirectDrawSurface_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
8281 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
8283 for (i = 0; i < sizeof(valid) / sizeof(*valid); ++i)
8285 RECT *rect = &valid[i];
8287 memset(&surface_desc, 0, sizeof(surface_desc));
8288 surface_desc.dwSize = sizeof(surface_desc);
8290 hr = IDirectDrawSurface_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
8291 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect %s, type %s.\n",
8292 hr, wine_dbgstr_rect(rect), resources[r].name);
8294 hr = IDirectDrawSurface_Unlock(surface, NULL);
8295 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
8298 for (i = 0; i < sizeof(invalid) / sizeof(*invalid); ++i)
8300 RECT *rect = &invalid[i];
8302 memset(&surface_desc, 1, sizeof(surface_desc));
8303 surface_desc.dwSize = sizeof(surface_desc);
8305 hr = IDirectDrawSurface_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
8306 ok(hr == resources[r].hr, "Lock returned %#x for rect %s, type %s.\n",
8307 hr, wine_dbgstr_rect(rect), resources[r].name);
8308 if (SUCCEEDED(hr))
8310 hr = IDirectDrawSurface_Unlock(surface, NULL);
8311 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
8313 else
8314 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8317 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8318 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
8319 hr, resources[r].name);
8320 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8321 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
8322 hr, resources[r].name);
8323 hr = IDirectDrawSurface_Unlock(surface, NULL);
8324 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
8326 hr = IDirectDrawSurface_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
8327 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#x).\n", wine_dbgstr_rect(&valid[0]), hr);
8328 hr = IDirectDrawSurface_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
8329 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#x).\n",
8330 wine_dbgstr_rect(&valid[0]), hr);
8332 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
8333 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
8335 hr = IDirectDrawSurface_Unlock(surface, NULL);
8336 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
8338 IDirectDrawSurface_Release(surface);
8341 done:
8342 IDirectDraw_Release(ddraw);
8343 DestroyWindow(window);
8346 static void test_yv12_overlay(void)
8348 IDirectDrawSurface *src_surface, *dst_surface;
8349 RECT rect = {13, 17, 14, 18};
8350 unsigned int offset, y;
8351 unsigned char *base;
8352 DDSURFACEDESC desc;
8353 IDirectDraw *ddraw;
8354 HWND window;
8355 HRESULT hr;
8357 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8358 0, 0, 640, 480, 0, 0, 0, 0);
8359 ddraw = create_ddraw();
8360 ok(!!ddraw, "Failed to create a ddraw object.\n");
8361 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8362 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8364 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
8366 skip("Failed to create a YV12 overlay, skipping test.\n");
8367 goto done;
8370 memset(&desc, 0, sizeof(desc));
8371 desc.dwSize = sizeof(desc);
8372 hr = IDirectDrawSurface_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
8373 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8375 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
8376 "Got unexpected flags %#x.\n", desc.dwFlags);
8377 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
8378 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
8379 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
8380 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
8381 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
8382 /* The overlay pitch seems to have 256 byte alignment. */
8383 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
8385 /* Fill the surface with some data for the blit test. */
8386 base = desc.lpSurface;
8387 /* Luminance */
8388 for (y = 0; y < desc.dwHeight; ++y)
8390 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
8392 /* V */
8393 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
8395 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
8397 /* U */
8398 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
8400 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
8403 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
8404 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8406 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
8407 * other block-based formats like DXT the entire Y channel is stored in
8408 * one big chunk of memory, followed by the chroma channels. So partial
8409 * locks do not really make sense. Show that they are allowed nevertheless
8410 * and the offset points into the luminance data. */
8411 hr = IDirectDrawSurface_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
8412 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8413 offset = ((const unsigned char *)desc.lpSurface - base);
8414 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
8415 offset, rect.top * U1(desc).lPitch + rect.left);
8416 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
8417 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8419 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
8421 /* Windows XP with a Radeon X1600 GPU refuses to create a second
8422 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
8423 skip("Failed to create a second YV12 surface, skipping blit test.\n");
8424 IDirectDrawSurface_Release(src_surface);
8425 goto done;
8428 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
8429 /* VMware rejects YV12 blits. This behavior has not been seen on real
8430 * hardware yet, so mark it broken. */
8431 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
8433 if (SUCCEEDED(hr))
8435 memset(&desc, 0, sizeof(desc));
8436 desc.dwSize = sizeof(desc);
8437 hr = IDirectDrawSurface_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
8438 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8440 base = desc.lpSurface;
8441 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
8442 base += desc.dwHeight * U1(desc).lPitch;
8443 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
8444 base += desc.dwHeight / 4 * U1(desc).lPitch;
8445 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
8447 hr = IDirectDrawSurface_Unlock(dst_surface, NULL);
8448 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8451 IDirectDrawSurface_Release(dst_surface);
8452 IDirectDrawSurface_Release(src_surface);
8453 done:
8454 IDirectDraw_Release(ddraw);
8455 DestroyWindow(window);
8458 static void test_offscreen_overlay(void)
8460 IDirectDrawSurface *overlay, *offscreen, *primary;
8461 DDSURFACEDESC surface_desc;
8462 IDirectDraw *ddraw;
8463 HWND window;
8464 HRESULT hr;
8465 HDC dc;
8467 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8468 0, 0, 640, 480, 0, 0, 0, 0);
8469 ddraw = create_ddraw();
8470 ok(!!ddraw, "Failed to create a ddraw object.\n");
8471 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8472 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8474 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
8476 skip("Failed to create a UYVY overlay, skipping test.\n");
8477 goto done;
8480 memset(&surface_desc, 0, sizeof(surface_desc));
8481 surface_desc.dwSize = sizeof(surface_desc);
8482 surface_desc.dwFlags = DDSD_CAPS;
8483 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8484 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8485 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
8487 /* On Windows 7, and probably Vista, UpdateOverlay() will return
8488 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
8489 * surface prevents this by disabling the dwm. */
8490 hr = IDirectDrawSurface_GetDC(primary, &dc);
8491 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8492 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
8493 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8495 /* Try to overlay a NULL surface. */
8496 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
8497 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8498 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
8499 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8501 /* Try to overlay an offscreen surface. */
8502 memset(&surface_desc, 0, sizeof(surface_desc));
8503 surface_desc.dwSize = sizeof(surface_desc);
8504 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
8505 surface_desc.dwWidth = 64;
8506 surface_desc.dwHeight = 64;
8507 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8508 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
8509 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
8510 surface_desc.ddpfPixelFormat.dwFourCC = 0;
8511 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
8512 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
8513 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
8514 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
8515 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
8516 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
8518 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
8519 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
8521 /* Try to overlay the primary with a non-overlay surface. */
8522 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
8523 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
8524 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
8525 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
8527 IDirectDrawSurface_Release(offscreen);
8528 IDirectDrawSurface_Release(primary);
8529 IDirectDrawSurface_Release(overlay);
8530 done:
8531 IDirectDraw_Release(ddraw);
8532 DestroyWindow(window);
8535 static void test_overlay_rect(void)
8537 IDirectDrawSurface *overlay, *primary;
8538 DDSURFACEDESC surface_desc;
8539 RECT rect = {0, 0, 64, 64};
8540 IDirectDraw *ddraw;
8541 LONG pos_x, pos_y;
8542 HRESULT hr, hr2;
8543 HWND window;
8544 HDC dc;
8546 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8547 0, 0, 640, 480, 0, 0, 0, 0);
8548 ddraw = create_ddraw();
8549 ok(!!ddraw, "Failed to create a ddraw object.\n");
8550 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8551 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8553 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
8555 skip("Failed to create a UYVY overlay, skipping test.\n");
8556 goto done;
8559 memset(&surface_desc, 0, sizeof(surface_desc));
8560 surface_desc.dwSize = sizeof(surface_desc);
8561 surface_desc.dwFlags = DDSD_CAPS;
8562 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8563 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8564 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
8566 /* On Windows 7, and probably Vista, UpdateOverlay() will return
8567 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
8568 * surface prevents this by disabling the dwm. */
8569 hr = IDirectDrawSurface_GetDC(primary, &dc);
8570 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8571 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
8572 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8574 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
8575 * used. This is not true in Windows Vista and earlier, but changed in
8576 * Windows 7. */
8577 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
8578 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
8579 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
8580 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
8581 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
8582 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8584 /* Show that the overlay position is the (top, left) coordinate of the
8585 * destination rectangle. */
8586 OffsetRect(&rect, 32, 16);
8587 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
8588 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
8589 pos_x = -1; pos_y = -1;
8590 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
8591 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
8592 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
8593 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
8595 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
8596 * seen that the overlay overlays the whole primary(==screen). */
8597 hr2 = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
8598 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
8599 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
8600 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
8601 if (SUCCEEDED(hr2))
8603 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
8604 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
8606 else
8608 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
8609 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
8612 /* The position cannot be retrieved when the overlay is not shown. */
8613 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
8614 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
8615 pos_x = -1; pos_y = -1;
8616 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
8617 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
8618 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
8619 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
8621 IDirectDrawSurface_Release(primary);
8622 IDirectDrawSurface_Release(overlay);
8623 done:
8624 IDirectDraw_Release(ddraw);
8625 DestroyWindow(window);
8628 static void test_blt(void)
8630 IDirectDrawSurface *surface, *rt;
8631 DDSURFACEDESC surface_desc;
8632 IDirect3DDevice *device;
8633 IDirectDraw *ddraw;
8634 unsigned int i;
8635 ULONG refcount;
8636 HWND window;
8637 HRESULT hr;
8639 static struct
8641 RECT src_rect;
8642 RECT dst_rect;
8643 HRESULT hr;
8645 test_data[] =
8647 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
8648 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
8649 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
8650 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
8651 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
8652 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
8653 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
8654 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
8655 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
8656 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
8659 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8660 0, 0, 640, 480, 0, 0, 0, 0);
8661 ddraw = create_ddraw();
8662 ok(!!ddraw, "Failed to create a ddraw object.\n");
8663 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8665 skip("Failed to create a 3D device, skipping test.\n");
8666 IDirectDraw_Release(ddraw);
8667 DestroyWindow(window);
8668 return;
8671 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
8672 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8674 memset(&surface_desc, 0, sizeof(surface_desc));
8675 surface_desc.dwSize = sizeof(surface_desc);
8676 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
8677 surface_desc.dwWidth = 640;
8678 surface_desc.dwHeight = 480;
8679 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8680 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8681 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8683 hr = IDirectDrawSurface_Blt(surface, NULL, surface, NULL, 0, NULL);
8684 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8686 hr = IDirectDrawSurface_Blt(surface, NULL, rt, NULL, 0, NULL);
8687 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8689 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
8691 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
8692 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
8693 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
8695 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
8696 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
8697 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
8700 IDirectDrawSurface_Release(surface);
8701 IDirectDrawSurface_Release(rt);
8702 refcount = IDirect3DDevice_Release(device);
8703 ok(!refcount, "Device has %u references left.\n", refcount);
8704 IDirectDraw_Release(ddraw);
8705 DestroyWindow(window);
8708 static void test_getdc(void)
8710 IDirectDrawSurface *surface, *surface2, *tmp;
8711 DDSURFACEDESC surface_desc, map_desc;
8712 DDSCAPS caps = {DDSCAPS_COMPLEX};
8713 IDirectDraw *ddraw;
8714 unsigned int i;
8715 HWND window;
8716 HDC dc, dc2;
8717 HRESULT hr;
8719 static const struct
8721 const char *name;
8722 DDPIXELFORMAT format;
8723 BOOL getdc_supported;
8724 HRESULT alt_result;
8726 test_data[] =
8728 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
8729 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
8730 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
8731 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
8732 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
8733 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
8734 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
8735 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
8736 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
8737 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
8738 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
8739 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
8740 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
8741 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
8742 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
8743 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
8744 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
8745 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
8746 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
8747 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
8748 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
8749 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
8750 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
8751 * This is not implemented in wine yet, so disable the test for now.
8752 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
8753 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
8754 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
8756 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
8757 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
8758 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
8759 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
8760 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
8761 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
8762 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
8763 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
8764 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
8765 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
8766 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
8767 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
8768 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
8769 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
8772 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8773 0, 0, 640, 480, 0, 0, 0, 0);
8774 ddraw = create_ddraw();
8775 ok(!!ddraw, "Failed to create a ddraw object.\n");
8776 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8777 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8779 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
8781 memset(&surface_desc, 0, sizeof(surface_desc));
8782 surface_desc.dwSize = sizeof(surface_desc);
8783 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8784 surface_desc.dwWidth = 64;
8785 surface_desc.dwHeight = 64;
8786 U4(surface_desc).ddpfPixelFormat = test_data[i].format;
8787 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8789 if (FAILED(IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
8791 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8792 if (FAILED(hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
8794 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
8795 continue;
8799 dc = (void *)0x1234;
8800 hr = IDirectDrawSurface_GetDC(surface, &dc);
8801 if (test_data[i].getdc_supported)
8802 ok(SUCCEEDED(hr) || (test_data[i].alt_result && hr == test_data[i].alt_result),
8803 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
8804 else
8805 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
8807 if (SUCCEEDED(hr))
8809 unsigned int width_bytes;
8810 DIBSECTION dib;
8811 HBITMAP bitmap;
8812 DWORD type;
8813 int size;
8815 type = GetObjectType(dc);
8816 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
8817 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
8818 type = GetObjectType(bitmap);
8819 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
8821 size = GetObjectA(bitmap, sizeof(dib), &dib);
8822 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
8823 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
8824 dib.dsBm.bmType, test_data[i].name);
8825 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
8826 dib.dsBm.bmWidth, test_data[i].name);
8827 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
8828 dib.dsBm.bmHeight, test_data[i].name);
8829 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
8830 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
8831 dib.dsBm.bmWidthBytes, test_data[i].name);
8832 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
8833 dib.dsBm.bmPlanes, test_data[i].name);
8834 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
8835 "Got unexpected bit count %d for format %s.\n",
8836 dib.dsBm.bmBitsPixel, test_data[i].name);
8837 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
8838 dib.dsBm.bmBits, test_data[i].name);
8840 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
8841 dib.dsBmih.biSize, test_data[i].name);
8842 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
8843 dib.dsBmih.biHeight, test_data[i].name);
8844 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
8845 dib.dsBmih.biHeight, test_data[i].name);
8846 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
8847 dib.dsBmih.biPlanes, test_data[i].name);
8848 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
8849 "Got unexpected bit count %u for format %s.\n",
8850 dib.dsBmih.biBitCount, test_data[i].name);
8851 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
8852 || broken(U2(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
8853 "Got unexpected compression %#x for format %s.\n",
8854 dib.dsBmih.biCompression, test_data[i].name);
8855 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
8856 dib.dsBmih.biSizeImage, test_data[i].name);
8857 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
8858 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
8859 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
8860 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
8861 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
8862 dib.dsBmih.biClrUsed, test_data[i].name);
8863 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
8864 dib.dsBmih.biClrImportant, test_data[i].name);
8866 if (dib.dsBmih.biCompression == BI_BITFIELDS)
8868 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
8869 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
8870 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
8871 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
8872 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
8873 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
8875 else
8877 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
8878 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
8879 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
8881 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
8882 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
8884 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8885 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
8887 else
8889 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
8892 IDirectDrawSurface_Release(surface);
8894 if (FAILED(hr))
8895 continue;
8897 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8898 if (FAILED(hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
8900 skip("Failed to create mip-mapped texture for format %s (hr %#x), skipping tests.\n",
8901 test_data[i].name, hr);
8902 continue;
8905 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
8906 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
8907 hr = IDirectDrawSurface_GetAttachedSurface(tmp, &caps, &surface2);
8908 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
8909 IDirectDrawSurface_Release(tmp);
8911 hr = IDirectDrawSurface_GetDC(surface, &dc);
8912 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
8913 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8914 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
8915 hr = IDirectDrawSurface_GetDC(surface2, &dc);
8916 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
8917 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
8918 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
8920 hr = IDirectDrawSurface_GetDC(surface, &dc);
8921 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
8922 dc2 = (void *)0x1234;
8923 hr = IDirectDrawSurface_GetDC(surface, &dc2);
8924 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
8925 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
8926 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8927 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
8928 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8929 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
8931 map_desc.dwSize = sizeof(map_desc);
8932 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8933 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
8934 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8935 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
8936 hr = IDirectDrawSurface_Unlock(surface, NULL);
8937 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
8938 hr = IDirectDrawSurface_Unlock(surface, NULL);
8939 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
8941 hr = IDirectDrawSurface_GetDC(surface, &dc);
8942 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
8943 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8944 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
8945 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8946 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
8948 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8949 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
8950 hr = IDirectDrawSurface_GetDC(surface, &dc);
8951 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
8952 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8953 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
8954 hr = IDirectDrawSurface_Unlock(surface, NULL);
8955 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
8957 hr = IDirectDrawSurface_GetDC(surface, &dc);
8958 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
8959 hr = IDirectDrawSurface_GetDC(surface2, &dc2);
8960 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
8961 hr = IDirectDrawSurface_ReleaseDC(surface2, dc2);
8962 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
8963 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8964 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
8966 hr = IDirectDrawSurface_GetDC(surface2, &dc);
8967 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
8968 hr = IDirectDrawSurface_GetDC(surface, &dc2);
8969 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
8970 hr = IDirectDrawSurface_ReleaseDC(surface, dc2);
8971 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
8972 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
8973 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
8975 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8976 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
8977 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8978 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
8979 hr = IDirectDrawSurface_Unlock(surface2, NULL);
8980 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
8981 hr = IDirectDrawSurface_Unlock(surface, NULL);
8982 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
8984 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8985 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
8986 hr = IDirectDrawSurface_GetDC(surface, &dc);
8987 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
8988 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8989 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
8990 hr = IDirectDrawSurface_Unlock(surface, NULL);
8991 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
8993 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8994 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
8995 hr = IDirectDrawSurface_GetDC(surface, &dc);
8996 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
8997 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8998 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
8999 hr = IDirectDrawSurface_Unlock(surface2, NULL);
9000 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
9002 hr = IDirectDrawSurface_GetDC(surface, &dc);
9003 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9004 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9005 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
9006 hr = IDirectDrawSurface_Unlock(surface2, NULL);
9007 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
9008 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9009 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9011 hr = IDirectDrawSurface_GetDC(surface2, &dc);
9012 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9013 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9014 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
9015 hr = IDirectDrawSurface_Unlock(surface, NULL);
9016 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
9017 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
9018 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9020 hr = IDirectDrawSurface_Unlock(surface, NULL);
9021 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9022 hr = IDirectDrawSurface_GetDC(surface2, &dc);
9023 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9024 hr = IDirectDrawSurface_Unlock(surface, NULL);
9025 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9026 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
9027 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9028 hr = IDirectDrawSurface_Unlock(surface, NULL);
9029 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9031 hr = IDirectDrawSurface_Unlock(surface2, NULL);
9032 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9033 hr = IDirectDrawSurface_GetDC(surface, &dc);
9034 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
9035 hr = IDirectDrawSurface_Unlock(surface2, NULL);
9036 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9037 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
9038 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
9039 hr = IDirectDrawSurface_Unlock(surface2, NULL);
9040 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
9042 IDirectDrawSurface_Release(surface2);
9043 IDirectDrawSurface_Release(surface);
9046 IDirectDraw_Release(ddraw);
9047 DestroyWindow(window);
9050 START_TEST(ddraw1)
9052 IDirectDraw *ddraw;
9053 DEVMODEW current_mode;
9055 if (!(ddraw = create_ddraw()))
9057 skip("Failed to create a ddraw object, skipping tests.\n");
9058 return;
9060 IDirectDraw_Release(ddraw);
9062 memset(&current_mode, 0, sizeof(current_mode));
9063 current_mode.dmSize = sizeof(current_mode);
9064 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
9065 registry_mode.dmSize = sizeof(registry_mode);
9066 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
9067 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
9068 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
9070 skip("Current mode does not match registry mode, skipping test.\n");
9071 return;
9074 test_coop_level_create_device_window();
9075 test_clipper_blt();
9076 test_coop_level_d3d_state();
9077 test_surface_interface_mismatch();
9078 test_coop_level_threaded();
9079 test_viewport();
9080 test_zenable();
9081 test_ck_rgba();
9082 test_ck_default();
9083 test_ck_complex();
9084 test_surface_qi();
9085 test_device_qi();
9086 test_wndproc();
9087 test_window_style();
9088 test_redundant_mode_set();
9089 test_coop_level_mode_set();
9090 test_coop_level_mode_set_multi();
9091 test_initialize();
9092 test_coop_level_surf_create();
9093 test_coop_level_multi_window();
9094 test_clear_rect_count();
9095 test_coop_level_activateapp();
9096 test_unsupported_formats();
9097 test_rt_caps();
9098 test_primary_caps();
9099 test_surface_lock();
9100 test_surface_discard();
9101 test_flip();
9102 test_sysmem_overlay();
9103 test_primary_palette();
9104 test_surface_attachment();
9105 test_pixel_format();
9106 test_create_surface_pitch();
9107 test_mipmap();
9108 test_palette_complex();
9109 test_p8_blit();
9110 test_material();
9111 test_lighting();
9112 test_palette_gdi();
9113 test_palette_alpha();
9114 test_lost_device();
9115 test_surface_desc_lock();
9116 test_texturemapblend();
9117 test_viewport_clear_rect();
9118 test_color_fill();
9119 test_colorkey_precision();
9120 test_range_colorkey();
9121 test_shademode();
9122 test_lockrect_invalid();
9123 test_yv12_overlay();
9124 test_offscreen_overlay();
9125 test_overlay_rect();
9126 test_blt();
9127 test_getdc();