include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / ddraw / tests / ddraw1.c
blob960477446353fdd06f690fab5287b87a5c662e9e
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
21 #define COBJMACROS
23 #include "wine/test.h"
24 #include <limits.h>
25 #include <math.h>
26 #include "ddrawi.h"
27 #include "d3dhal.h"
29 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
30 static DEVMODEW registry_mode;
32 static HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *);
34 struct vec2
36 float x, y;
39 struct vec4
41 float x, y, z, w;
44 struct create_window_thread_param
46 HWND window;
47 HANDLE window_created;
48 HANDLE destroy_window;
49 HANDLE thread;
52 static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff)
54 unsigned int diff = x > y ? x - y : y - x;
56 return diff <= max_diff;
59 static BOOL compare_float(float f, float g, unsigned int ulps)
61 int x = *(int *)&f;
62 int y = *(int *)&g;
64 if (x < 0)
65 x = INT_MIN - x;
66 if (y < 0)
67 y = INT_MIN - y;
69 return compare_uint(x, y, ulps);
72 static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
74 return compare_float(vec->x, x, ulps)
75 && compare_float(vec->y, y, ulps)
76 && compare_float(vec->z, z, ulps)
77 && compare_float(vec->w, w, ulps);
80 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
82 return compare_uint(c1 & 0xff, c2 & 0xff, max_diff)
83 && compare_uint((c1 >> 8) & 0xff, (c2 >> 8) & 0xff, max_diff)
84 && compare_uint((c1 >> 16) & 0xff, (c2 >> 16) & 0xff, max_diff)
85 && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff);
88 static void get_virtual_rect(RECT *rect)
90 rect->left = GetSystemMetrics(SM_XVIRTUALSCREEN);
91 rect->top = GetSystemMetrics(SM_YVIRTUALSCREEN);
92 rect->right = rect->left + GetSystemMetrics(SM_CXVIRTUALSCREEN);
93 rect->bottom = rect->top + GetSystemMetrics(SM_CYVIRTUALSCREEN);
96 /* Try to make sure pending X events have been processed before continuing */
97 static void flush_events(void)
99 int diff = 200;
100 DWORD time;
101 MSG msg;
103 time = GetTickCount() + diff;
104 while (diff > 0)
106 if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT)
107 break;
108 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
109 DispatchMessageA(&msg);
110 diff = time - GetTickCount();
114 static BOOL ddraw_get_identifier(IDirectDraw *ddraw, DDDEVICEIDENTIFIER *identifier)
116 IDirectDraw4 *ddraw4;
117 HRESULT hr;
119 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw4, (void **)&ddraw4);
120 ok(SUCCEEDED(hr), "Failed to get IDirectDraw4 interface, hr %#lx.\n", hr);
121 hr = IDirectDraw4_GetDeviceIdentifier(ddraw4, identifier, 0);
122 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#lx.\n", hr);
123 IDirectDraw4_Release(ddraw4);
125 return SUCCEEDED(hr);
128 static BOOL ddraw_is_warp(IDirectDraw *ddraw)
130 DDDEVICEIDENTIFIER identifier;
132 return strcmp(winetest_platform, "wine")
133 && ddraw_get_identifier(ddraw, &identifier)
134 && strstr(identifier.szDriver, "warp");
137 static BOOL ddraw_is_vendor(IDirectDraw *ddraw, DWORD vendor)
139 DDDEVICEIDENTIFIER identifier;
141 return strcmp(winetest_platform, "wine")
142 && ddraw_get_identifier(ddraw, &identifier)
143 && identifier.dwVendorId == vendor;
146 static BOOL ddraw_is_amd(IDirectDraw *ddraw)
148 return ddraw_is_vendor(ddraw, 0x1002);
151 static BOOL ddraw_is_intel(IDirectDraw *ddraw)
153 return ddraw_is_vendor(ddraw, 0x8086);
156 static BOOL ddraw_is_nvidia(IDirectDraw *ddraw)
158 return ddraw_is_vendor(ddraw, 0x10de);
161 static BOOL ddraw_is_vmware(IDirectDraw *ddraw)
163 return ddraw_is_vendor(ddraw, 0x15ad);
166 static BOOL is_software_device_type(const GUID *device_guid)
168 return device_guid != &IID_IDirect3DHALDevice;
171 static IDirectDrawSurface *create_overlay(IDirectDraw *ddraw,
172 unsigned int width, unsigned int height, DWORD format)
174 IDirectDrawSurface *surface;
175 DDSURFACEDESC desc;
177 memset(&desc, 0, sizeof(desc));
178 desc.dwSize = sizeof(desc);
179 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
180 desc.dwWidth = width;
181 desc.dwHeight = height;
182 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
183 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
184 desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
185 desc.ddpfPixelFormat.dwFourCC = format;
187 if (FAILED(IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL)))
188 return NULL;
189 return surface;
192 static HWND create_window(void)
194 RECT r = {0, 0, 640, 480};
196 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
198 return CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
199 CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
202 static DWORD WINAPI create_window_thread_proc(void *param)
204 struct create_window_thread_param *p = param;
205 DWORD res;
206 BOOL ret;
208 p->window = create_window();
209 ret = SetEvent(p->window_created);
210 ok(ret, "SetEvent failed, last error %lu.\n", GetLastError());
212 for (;;)
214 MSG msg;
216 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
217 DispatchMessageA(&msg);
218 res = WaitForSingleObject(p->destroy_window, 100);
219 if (res == WAIT_OBJECT_0)
220 break;
221 if (res != WAIT_TIMEOUT)
223 ok(0, "Wait failed (%#lx), last error %lu.\n", res, GetLastError());
224 break;
228 DestroyWindow(p->window);
230 return 0;
233 static void create_window_thread(struct create_window_thread_param *p)
235 DWORD res, tid;
237 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
238 ok(!!p->window_created, "CreateEvent failed, last error %lu.\n", GetLastError());
239 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
240 ok(!!p->destroy_window, "CreateEvent failed, last error %lu.\n", GetLastError());
241 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
242 ok(!!p->thread, "Failed to create thread, last error %lu.\n", GetLastError());
243 res = WaitForSingleObject(p->window_created, INFINITE);
244 ok(res == WAIT_OBJECT_0, "Wait failed (%#lx), last error %lu.\n", res, GetLastError());
247 static void destroy_window_thread(struct create_window_thread_param *p)
249 SetEvent(p->destroy_window);
250 WaitForSingleObject(p->thread, INFINITE);
251 CloseHandle(p->destroy_window);
252 CloseHandle(p->window_created);
253 CloseHandle(p->thread);
256 static IDirectDrawSurface *get_depth_stencil(IDirect3DDevice *device)
258 IDirectDrawSurface *rt, *ret;
259 DDSCAPS caps = {DDSCAPS_ZBUFFER};
260 HRESULT hr;
262 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
263 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
264 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ret);
265 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#lx.\n", hr);
266 IDirectDrawSurface_Release(rt);
267 return ret;
270 /* Free original_modes after finished using it */
271 static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
273 unsigned int number, size = 2, count = 0, index = 0;
274 DISPLAY_DEVICEW display_device;
275 DEVMODEW *modes, *tmp;
277 if (!(modes = malloc(size * sizeof(*modes))))
278 return FALSE;
280 display_device.cb = sizeof(display_device);
281 while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
283 /* Skip software devices */
284 if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
285 continue;
287 if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
288 continue;
290 if (count >= size)
292 size *= 2;
293 if (!(tmp = realloc(modes, size * sizeof(*modes))))
295 free(modes);
296 return FALSE;
298 modes = tmp;
301 memset(&modes[count], 0, sizeof(modes[count]));
302 modes[count].dmSize = sizeof(modes[count]);
303 if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
305 free(modes);
306 return FALSE;
309 lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
312 *original_modes = modes;
313 *display_count = count;
314 return TRUE;
317 static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
319 unsigned int index;
320 LONG ret;
322 for (index = 0; index < count; ++index)
324 ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
325 CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
326 if (ret != DISP_CHANGE_SUCCESSFUL)
327 return FALSE;
329 ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
330 return ret == DISP_CHANGE_SUCCESSFUL;
333 static HRESULT set_display_mode(IDirectDraw *ddraw, DWORD width, DWORD height)
335 if (SUCCEEDED(IDirectDraw_SetDisplayMode(ddraw, width, height, 32)))
336 return DD_OK;
337 return IDirectDraw_SetDisplayMode(ddraw, width, height, 24);
340 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
342 RECT rect = {x, y, x + 1, y + 1};
343 DDSURFACEDESC surface_desc;
344 D3DCOLOR color;
345 HRESULT hr;
347 memset(&surface_desc, 0, sizeof(surface_desc));
348 surface_desc.dwSize = sizeof(surface_desc);
350 hr = IDirectDrawSurface_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
351 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
352 if (FAILED(hr))
353 return 0xdeadbeef;
355 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
357 hr = IDirectDrawSurface_Unlock(surface, NULL);
358 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
360 return color;
363 static void fill_surface(IDirectDrawSurface *surface, D3DCOLOR color)
365 DDSURFACEDESC surface_desc = {sizeof(surface_desc)};
366 HRESULT hr;
367 unsigned int x, y;
368 DWORD *ptr;
370 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
371 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
373 for (y = 0; y < surface_desc.dwHeight; ++y)
375 ptr = (DWORD *)((BYTE *)surface_desc.lpSurface + y * surface_desc.lPitch);
376 for (x = 0; x < surface_desc.dwWidth; ++x)
378 ptr[x] = color;
382 hr = IDirectDrawSurface_Unlock(surface, NULL);
383 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
386 static void check_rect(IDirectDrawSurface *surface, RECT r)
388 LONG x_coords[2][2] =
390 {r.left - 1, r.left + 1},
391 {r.right + 1, r.right - 1},
393 LONG y_coords[2][2] =
395 {r.top - 1, r.top + 1},
396 {r.bottom + 1, r.bottom - 1}
398 unsigned int i, j, x_side, y_side, color;
399 LONG x, y;
401 for (i = 0; i < 2; ++i)
403 for (j = 0; j < 2; ++j)
405 for (x_side = 0; x_side < 2; ++x_side)
407 for (y_side = 0; y_side < 2; ++y_side)
409 unsigned int expected = (x_side == 1 && y_side == 1) ? 0x00ffffff : 0x00000000;
411 x = x_coords[i][x_side];
412 y = y_coords[j][y_side];
413 if (x < 0 || x >= 640 || y < 0 || y >= 480)
414 continue;
415 color = get_surface_color(surface, x, y);
416 ok(color == expected, "Pixel (%ld, %ld) has color %08x, expected %08x.\n", x, y, color, expected);
423 static void emit_process_vertices(void **ptr, DWORD flags, WORD base_idx, DWORD vertex_count)
425 D3DINSTRUCTION *inst = *ptr;
426 D3DPROCESSVERTICES *pv = (D3DPROCESSVERTICES *)(inst + 1);
428 inst->bOpcode = D3DOP_PROCESSVERTICES;
429 inst->bSize = sizeof(*pv);
430 inst->wCount = 1;
432 pv->dwFlags = flags;
433 pv->wStart = base_idx;
434 pv->wDest = 0;
435 pv->dwCount = vertex_count;
436 pv->dwReserved = 0;
438 *ptr = pv + 1;
441 static void emit_set_ts(void **ptr, D3DTRANSFORMSTATETYPE state, DWORD value)
443 D3DINSTRUCTION *inst = *ptr;
444 D3DSTATE *ts = (D3DSTATE *)(inst + 1);
446 inst->bOpcode = D3DOP_STATETRANSFORM;
447 inst->bSize = sizeof(*ts);
448 inst->wCount = 1;
450 ts->dtstTransformStateType = state;
451 ts->dwArg[0] = value;
453 *ptr = ts + 1;
456 static void emit_set_ls(void **ptr, D3DLIGHTSTATETYPE state, DWORD value)
458 D3DINSTRUCTION *inst = *ptr;
459 D3DSTATE *ls = (D3DSTATE *)(inst + 1);
461 inst->bOpcode = D3DOP_STATELIGHT;
462 inst->bSize = sizeof(*ls);
463 inst->wCount = 1;
465 ls->dlstLightStateType = state;
466 ls->dwArg[0] = value;
468 *ptr = ls + 1;
471 static void emit_set_rs(void **ptr, D3DRENDERSTATETYPE state, DWORD value)
473 D3DINSTRUCTION *inst = *ptr;
474 D3DSTATE *rs = (D3DSTATE *)(inst + 1);
476 inst->bOpcode = D3DOP_STATERENDER;
477 inst->bSize = sizeof(*rs);
478 inst->wCount = 1;
480 rs->drstRenderStateType = state;
481 rs->dwArg[0] = value;
483 *ptr = rs + 1;
486 static void emit_tquad(void **ptr, WORD base_idx)
488 D3DINSTRUCTION *inst = *ptr;
489 D3DTRIANGLE *tri = (D3DTRIANGLE *)(inst + 1);
491 inst->bOpcode = D3DOP_TRIANGLE;
492 inst->bSize = sizeof(*tri);
493 inst->wCount = 2;
495 tri->v1 = base_idx;
496 tri->v2 = base_idx + 1;
497 tri->v3 = base_idx + 2;
498 tri->wFlags = D3DTRIFLAG_START;
499 ++tri;
501 tri->v1 = base_idx + 2;
502 tri->v2 = base_idx + 1;
503 tri->v3 = base_idx + 3;
504 tri->wFlags = D3DTRIFLAG_ODD;
505 ++tri;
507 *ptr = tri;
510 static void emit_tquad_tlist(void **ptr, WORD base_idx)
512 D3DINSTRUCTION *inst = *ptr;
513 D3DTRIANGLE *tri = (D3DTRIANGLE *)(inst + 1);
515 inst->bOpcode = D3DOP_TRIANGLE;
516 inst->bSize = sizeof(*tri);
517 inst->wCount = 2;
519 tri->v1 = base_idx;
520 tri->v2 = base_idx + 1;
521 tri->v3 = base_idx + 2;
522 tri->wFlags = D3DTRIFLAG_START;
523 ++tri;
525 tri->v1 = base_idx + 2;
526 tri->v2 = base_idx + 3;
527 tri->v3 = base_idx;
528 tri->wFlags = D3DTRIFLAG_START;
529 ++tri;
531 *ptr = tri;
534 static void emit_tri_indices(void **ptr, WORD *indices, unsigned int primitive_count)
536 D3DINSTRUCTION *inst = *ptr;
537 D3DTRIANGLE *tri = (D3DTRIANGLE *)(inst + 1);
538 unsigned int i;
540 inst->bOpcode = D3DOP_TRIANGLE;
541 inst->bSize = sizeof(*tri);
542 inst->wCount = primitive_count;
544 for (i = 0; i < primitive_count; ++i)
546 tri->v1 = indices[i * 3];
547 tri->v2 = indices[i * 3 + 1];
548 tri->v3 = indices[i * 3 + 2];
549 tri->wFlags = D3DTRIFLAG_START;
550 ++tri;
552 *ptr = tri;
555 static void emit_texture_load(void **ptr, D3DTEXTUREHANDLE dst_texture,
556 D3DTEXTUREHANDLE src_texture)
558 D3DINSTRUCTION *instruction = *ptr;
559 D3DTEXTURELOAD *texture_load = (D3DTEXTURELOAD *)(instruction + 1);
561 instruction->bOpcode = D3DOP_TEXTURELOAD;
562 instruction->bSize = sizeof(*texture_load);
563 instruction->wCount = 1;
565 texture_load->hDestTexture = dst_texture;
566 texture_load->hSrcTexture = src_texture;
567 ++texture_load;
569 *ptr = texture_load;
572 static void emit_end(void **ptr)
574 D3DINSTRUCTION *inst = *ptr;
576 inst->bOpcode = D3DOP_EXIT;
577 inst->bSize = 0;
578 inst->wCount = 0;
580 *ptr = inst + 1;
583 static void set_execute_data(IDirect3DExecuteBuffer *execute_buffer, UINT vertex_count, UINT offset, UINT len)
585 D3DEXECUTEDATA exec_data;
586 HRESULT hr;
588 memset(&exec_data, 0, sizeof(exec_data));
589 exec_data.dwSize = sizeof(exec_data);
590 exec_data.dwVertexCount = vertex_count;
591 exec_data.dwInstructionOffset = offset;
592 exec_data.dwInstructionLength = len;
593 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
594 ok(SUCCEEDED(hr), "Failed to set execute data, hr %#lx.\n", hr);
597 static DWORD get_device_z_depth(IDirect3DDevice *device)
599 DDSCAPS caps = {DDSCAPS_ZBUFFER};
600 IDirectDrawSurface *ds, *rt;
601 DDSURFACEDESC desc;
602 HRESULT hr;
604 if (FAILED(IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt)))
605 return 0;
607 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ds);
608 IDirectDrawSurface_Release(rt);
609 if (FAILED(hr))
610 return 0;
612 desc.dwSize = sizeof(desc);
613 hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
614 IDirectDrawSurface_Release(ds);
615 if (FAILED(hr))
616 return 0;
618 return desc.dwZBufferBitDepth;
621 static IDirectDraw *create_ddraw(void)
623 IDirectDraw *ddraw;
625 if (FAILED(DirectDrawCreate(NULL, &ddraw, NULL)))
626 return NULL;
628 return ddraw;
631 static IDirect3DDevice *create_device_ex(IDirectDraw *ddraw, HWND window, DWORD coop_level, const GUID *device_guid)
633 /* Prefer 16 bit depth buffers because Nvidia gives us an unpadded D24 buffer if we ask
634 * for 24 bit and handles such buffers incorrectly in DDBLT_DEPTHFILL. AMD only supports
635 * 16 bit buffers in ddraw1/2. Stencil was added in ddraw4, so we cannot create a D24S8
636 * buffer here. */
637 static const DWORD z_depths[] = {16, 32, 24};
638 IDirectDrawSurface *surface, *ds;
639 IDirect3DDevice *device = NULL;
640 DDSURFACEDESC surface_desc;
641 unsigned int i;
642 HRESULT hr;
644 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, coop_level);
645 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
647 memset(&surface_desc, 0, sizeof(surface_desc));
648 surface_desc.dwSize = sizeof(surface_desc);
649 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
650 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
651 if (is_software_device_type(device_guid))
652 surface_desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
653 surface_desc.dwWidth = 640;
654 surface_desc.dwHeight = 480;
656 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
657 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
659 if (coop_level & DDSCL_NORMAL)
661 IDirectDrawClipper *clipper;
663 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
664 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
665 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
666 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
667 hr = IDirectDrawSurface_SetClipper(surface, clipper);
668 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#lx.\n", hr);
669 IDirectDrawClipper_Release(clipper);
672 /* We used to use EnumDevices() for this, but it seems
673 * D3DDEVICEDESC.dwDeviceZBufferBitDepth only has a very casual
674 * relationship with reality. */
675 for (i = 0; i < ARRAY_SIZE(z_depths); ++i)
677 memset(&surface_desc, 0, sizeof(surface_desc));
678 surface_desc.dwSize = sizeof(surface_desc);
679 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
680 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
681 if (is_software_device_type(device_guid))
682 surface_desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
683 surface_desc.dwZBufferBitDepth = z_depths[i];
684 surface_desc.dwWidth = 640;
685 surface_desc.dwHeight = 480;
686 if (FAILED(IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL)))
687 continue;
689 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
690 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#lx.\n", hr);
691 IDirectDrawSurface_Release(ds);
692 if (FAILED(hr))
693 continue;
695 if (SUCCEEDED(IDirectDrawSurface_QueryInterface(surface, device_guid, (void **)&device)))
696 break;
698 IDirectDrawSurface_DeleteAttachedSurface(surface, 0, ds);
701 IDirectDrawSurface_Release(surface);
702 return device;
705 static IDirect3DDevice *create_device(IDirectDraw *ddraw, HWND window, DWORD coop_level)
707 return create_device_ex(ddraw, window, coop_level, &IID_IDirect3DHALDevice);
710 static IDirect3DViewport *create_viewport(IDirect3DDevice *device, UINT x, UINT y, UINT w, UINT h)
712 IDirect3DViewport *viewport;
713 D3DVIEWPORT vp;
714 IDirect3D *d3d;
715 HRESULT hr;
717 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
718 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
719 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
720 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#lx.\n", hr);
721 hr = IDirect3DDevice_AddViewport(device, viewport);
722 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#lx.\n", hr);
723 memset(&vp, 0, sizeof(vp));
724 vp.dwSize = sizeof(vp);
725 vp.dwX = x;
726 vp.dwY = y;
727 vp.dwWidth = w;
728 vp.dwHeight = h;
729 vp.dvScaleX = (float)w / 2.0f;
730 vp.dvScaleY = (float)h / 2.0f;
731 vp.dvMaxX = 1.0f;
732 vp.dvMaxY = 1.0f;
733 vp.dvMinZ = 0.0f;
734 vp.dvMaxZ = 1.0f;
735 hr = IDirect3DViewport_SetViewport(viewport, &vp);
736 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#lx.\n", hr);
737 IDirect3D_Release(d3d);
739 return viewport;
742 static void viewport_set_background(IDirect3DDevice *device, IDirect3DViewport *viewport,
743 IDirect3DMaterial *material)
745 D3DMATERIALHANDLE material_handle;
746 HRESULT hr;
748 hr = IDirect3DMaterial2_GetHandle(material, device, &material_handle);
749 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#lx.\n", hr);
750 hr = IDirect3DViewport2_SetBackground(viewport, material_handle);
751 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#lx.\n", hr);
754 static void destroy_viewport(IDirect3DDevice *device, IDirect3DViewport *viewport)
756 HRESULT hr;
758 hr = IDirect3DDevice_DeleteViewport(device, viewport);
759 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#lx.\n", hr);
760 IDirect3DViewport_Release(viewport);
763 static IDirect3DMaterial *create_material(IDirect3DDevice *device, D3DMATERIAL *mat)
765 IDirect3DMaterial *material;
766 IDirect3D *d3d;
767 HRESULT hr;
769 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
770 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
771 hr = IDirect3D_CreateMaterial(d3d, &material, NULL);
772 ok(SUCCEEDED(hr), "Failed to create material, hr %#lx.\n", hr);
773 hr = IDirect3DMaterial_SetMaterial(material, mat);
774 ok(SUCCEEDED(hr), "Failed to set material data, hr %#lx.\n", hr);
775 IDirect3D_Release(d3d);
777 return material;
780 static IDirect3DMaterial *create_diffuse_material(IDirect3DDevice *device, float r, float g, float b, float a)
782 D3DMATERIAL mat;
784 memset(&mat, 0, sizeof(mat));
785 mat.dwSize = sizeof(mat);
786 mat.diffuse.r = r;
787 mat.diffuse.g = g;
788 mat.diffuse.b = b;
789 mat.diffuse.a = a;
791 return create_material(device, &mat);
794 static IDirect3DMaterial *create_diffuse_and_ambient_material(IDirect3DDevice *device,
795 float r, float g, float b, float a)
797 D3DMATERIAL mat;
799 memset(&mat, 0, sizeof(mat));
800 mat.dwSize = sizeof(mat);
801 mat.diffuse.r = r;
802 mat.diffuse.g = g;
803 mat.diffuse.b = b;
804 mat.diffuse.a = a;
806 mat.ambient.r = r;
807 mat.ambient.g = g;
808 mat.ambient.b = b;
809 mat.ambient.a = a;
811 return create_material(device, &mat);
814 static IDirect3DMaterial *create_emissive_material(IDirect3DDevice *device, float r, float g, float b, float a)
816 D3DMATERIAL mat;
818 memset(&mat, 0, sizeof(mat));
819 mat.dwSize = sizeof(mat);
820 mat.emissive.r = r;
821 mat.emissive.g = g;
822 mat.emissive.b = b;
823 mat.emissive.a = a;
825 return create_material(device, &mat);
828 static IDirect3DMaterial *create_specular_material(IDirect3DDevice *device,
829 float r, float g, float b, float a, float power)
831 D3DMATERIAL mat;
833 memset(&mat, 0, sizeof(mat));
834 mat.dwSize = sizeof(mat);
835 mat.specular.r = r;
836 mat.specular.g = g;
837 mat.specular.b = b;
838 mat.specular.a = a;
839 mat.power = power;
841 return create_material(device, &mat);
844 static void destroy_material(IDirect3DMaterial *material)
846 IDirect3DMaterial_Release(material);
849 struct message
851 UINT message;
852 BOOL check_wparam;
853 WPARAM expect_wparam;
856 static const struct message *expect_messages;
858 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
860 if (expect_messages && message == expect_messages->message)
862 if (expect_messages->check_wparam)
863 ok (wparam == expect_messages->expect_wparam,
864 "Got unexpected wparam %#Ix for message %#x, expected %#Ix.\n",
865 wparam, message, expect_messages->expect_wparam);
867 ++expect_messages;
870 return DefWindowProcA(hwnd, message, wparam, lparam);
873 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
874 * interface. This prevents subsequent SetCooperativeLevel() calls on a
875 * different window from failing with DDERR_HWNDALREADYSET. */
876 static void fix_wndproc(HWND window, LONG_PTR proc)
878 IDirectDraw *ddraw;
879 HRESULT hr;
881 if (!(ddraw = create_ddraw()))
882 return;
884 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
885 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
886 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
887 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
888 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
890 IDirectDraw_Release(ddraw);
893 static HRESULT CALLBACK restore_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
895 HRESULT hr = IDirectDrawSurface_Restore(surface);
896 ok(SUCCEEDED(hr) || hr == DDERR_IMPLICITLYCREATED, "Failed to restore surface, hr %#lx.\n", hr);
897 IDirectDrawSurface_Release(surface);
899 return DDENUMRET_OK;
902 static HRESULT restore_surfaces(IDirectDraw *ddraw)
904 return IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
905 NULL, NULL, restore_callback);
908 static void test_coop_level_create_device_window(void)
910 HWND focus_window, device_window;
911 IDirectDraw *ddraw;
912 HRESULT hr;
914 focus_window = create_window();
915 ddraw = create_ddraw();
916 ok(!!ddraw, "Failed to create a ddraw object.\n");
918 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
919 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
920 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
921 ok(!device_window, "Unexpected device window found.\n");
922 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
923 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
924 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
925 ok(!device_window, "Unexpected device window found.\n");
926 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
927 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
928 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
929 ok(!device_window, "Unexpected device window found.\n");
930 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
931 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
932 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
933 ok(!device_window, "Unexpected device window found.\n");
934 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
935 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#lx.\n", hr);
936 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
937 ok(!device_window, "Unexpected device window found.\n");
939 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
940 if (broken(hr == DDERR_INVALIDPARAMS))
942 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
943 IDirectDraw_Release(ddraw);
944 DestroyWindow(focus_window);
945 return;
948 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
949 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
950 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
951 ok(!device_window, "Unexpected device window found.\n");
952 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
953 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
954 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
955 ok(!device_window, "Unexpected device window found.\n");
957 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
958 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
959 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
960 ok(!device_window, "Unexpected device window found.\n");
961 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
962 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
963 ok(hr == DDERR_NOHWND, "Got unexpected hr %#lx.\n", hr);
964 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
965 ok(!!device_window, "Device window not found.\n");
967 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
968 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
969 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
970 ok(!device_window, "Unexpected device window found.\n");
971 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
972 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
973 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
974 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
975 ok(!!device_window, "Device window not found.\n");
977 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
978 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
979 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
980 ok(!device_window, "Unexpected device window found.\n");
981 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
982 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#lx.\n", hr);
983 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
984 ok(!device_window, "Unexpected device window found.\n");
985 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
986 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
987 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
988 ok(!device_window, "Unexpected device window found.\n");
989 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
990 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
991 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
992 ok(!!device_window, "Device window not found.\n");
994 IDirectDraw_Release(ddraw);
995 DestroyWindow(focus_window);
998 static void test_clipper_blt(void)
1000 IDirectDrawSurface *src_surface, *dst_surface;
1001 unsigned int color, i, j, x, y;
1002 RECT client_rect, src_rect;
1003 IDirectDrawClipper *clipper;
1004 DDSURFACEDESC surface_desc;
1005 IDirectDraw *ddraw;
1006 RGNDATA *rgn_data;
1007 ULONG refcount;
1008 HRGN r1, r2;
1009 HWND window;
1010 DDBLTFX fx;
1011 HRESULT hr;
1012 DWORD *ptr;
1013 DWORD ret;
1015 static const DWORD src_data[] =
1017 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
1018 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
1019 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
1021 static const unsigned int expected1[] =
1023 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
1024 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
1025 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
1026 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
1028 /* Nvidia on Windows seems to have an off-by-one error
1029 * when processing source rectangles. Our left = 1 and
1030 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
1031 * read as well, but only for the edge pixels on the
1032 * output image. The bug happens on the y axis as well,
1033 * but we only read one row there, and all source rows
1034 * contain the same data. This bug is not dependent on
1035 * the presence of a clipper. */
1036 static const D3DCOLOR expected1_broken[] =
1038 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
1039 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
1040 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
1041 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
1043 static const unsigned int expected2[] =
1045 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
1046 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
1047 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
1048 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
1051 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1052 10, 10, 640, 480, 0, 0, 0, 0);
1053 ShowWindow(window, SW_SHOW);
1054 ddraw = create_ddraw();
1055 ok(!!ddraw, "Failed to create a ddraw object.\n");
1057 ret = GetClientRect(window, &client_rect);
1058 ok(ret, "Failed to get client rect.\n");
1059 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
1060 ok(ret, "Failed to map client rect.\n");
1062 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1063 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
1065 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
1066 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
1067 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1068 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#lx.\n", hr);
1069 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
1070 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
1071 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1072 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#lx.\n", hr);
1073 rgn_data = malloc(ret);
1074 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
1075 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#lx.\n", hr);
1076 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#lx.\n", rgn_data->rdh.dwSize);
1077 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#lx.\n", rgn_data->rdh.iType);
1078 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %lu.\n", rgn_data->rdh.nCount);
1079 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
1080 "Got unexpected bounding rect %s, expected %s.\n",
1081 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
1082 free(rgn_data);
1084 r1 = CreateRectRgn(0, 0, 320, 240);
1085 ok(!!r1, "Failed to create region.\n");
1086 r2 = CreateRectRgn(320, 240, 640, 480);
1087 ok(!!r2, "Failed to create region.\n");
1088 CombineRgn(r1, r1, r2, RGN_OR);
1089 ret = GetRegionData(r1, 0, NULL);
1090 rgn_data = malloc(ret);
1091 ret = GetRegionData(r1, ret, rgn_data);
1092 ok(!!ret, "Failed to get region data.\n");
1094 DeleteObject(r2);
1095 DeleteObject(r1);
1097 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
1098 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#lx.\n", hr);
1099 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
1100 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
1101 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
1102 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#lx.\n", hr);
1104 free(rgn_data);
1106 memset(&surface_desc, 0, sizeof(surface_desc));
1107 surface_desc.dwSize = sizeof(surface_desc);
1108 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1109 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1110 surface_desc.dwWidth = 640;
1111 surface_desc.dwHeight = 480;
1112 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1113 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1114 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
1115 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
1116 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
1117 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
1119 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
1120 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#lx.\n", hr);
1121 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
1122 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#lx.\n", hr);
1124 memset(&fx, 0, sizeof(fx));
1125 fx.dwSize = sizeof(fx);
1126 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1127 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#lx.\n", hr);
1128 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1129 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#lx.\n", hr);
1131 hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
1132 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#lx.\n", hr);
1133 ok(surface_desc.lPitch == 2560, "Got unexpected surface pitch %lu.\n", surface_desc.lPitch);
1134 ptr = surface_desc.lpSurface;
1135 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
1136 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
1137 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
1138 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
1139 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#lx.\n", hr);
1141 hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
1142 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
1144 SetRect(&src_rect, 1, 1, 5, 2);
1145 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
1146 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
1147 for (i = 0; i < 4; ++i)
1149 for (j = 0; j < 4; ++j)
1151 x = 80 * ((2 * j) + 1);
1152 y = 60 * ((2 * i) + 1);
1153 color = get_surface_color(dst_surface, x, y);
1154 ok(compare_color(color, expected1[i * 4 + j], 1)
1155 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
1156 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
1160 fx.dwFillColor = 0xff0000ff;
1161 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1162 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#lx.\n", hr);
1163 for (i = 0; i < 4; ++i)
1165 for (j = 0; j < 4; ++j)
1167 x = 80 * ((2 * j) + 1);
1168 y = 60 * ((2 * i) + 1);
1169 color = get_surface_color(dst_surface, x, y);
1170 ok(compare_color(color, expected2[i * 4 + j], 1),
1171 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
1175 hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
1176 ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#lx.\n", hr);
1178 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
1179 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
1180 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1181 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#lx.\n", hr);
1182 DestroyWindow(window);
1183 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1184 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
1185 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
1186 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
1187 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1188 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#lx.\n", hr);
1189 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
1190 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#lx.\n", hr);
1191 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1192 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#lx.\n", hr);
1193 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1194 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#lx.\n", hr);
1196 IDirectDrawSurface_Release(dst_surface);
1197 IDirectDrawSurface_Release(src_surface);
1198 refcount = IDirectDrawClipper_Release(clipper);
1199 ok(!refcount, "Clipper has %lu references left.\n", refcount);
1200 IDirectDraw_Release(ddraw);
1203 static void test_coop_level_d3d_state(void)
1205 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1206 IDirectDrawSurface *rt, *surface;
1207 IDirect3DMaterial *background;
1208 IDirect3DViewport *viewport;
1209 IDirect3DDevice *device;
1210 D3DMATERIAL material;
1211 DDSURFACEDESC lock;
1212 unsigned int color;
1213 IDirectDraw *ddraw;
1214 HWND window;
1215 HRESULT hr;
1217 window = create_window();
1218 ddraw = create_ddraw();
1219 ok(!!ddraw, "Failed to create a ddraw object.\n");
1220 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1222 skip("Failed to create a 3D device, skipping test.\n");
1223 IDirectDraw_Release(ddraw);
1224 DestroyWindow(window);
1225 return;
1228 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1229 viewport = create_viewport(device, 0, 0, 640, 480);
1230 viewport_set_background(device, viewport, background);
1232 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1233 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1234 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1235 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1236 color = get_surface_color(rt, 320, 240);
1237 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1239 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1240 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1241 hr = IDirectDrawSurface_IsLost(rt);
1242 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
1244 memset(&lock, 0, sizeof(lock));
1245 lock.dwSize = sizeof(lock);
1246 lock.lpSurface = (void *)0xdeadbeef;
1247 hr = IDirectDrawSurface_Lock(rt, NULL, &lock, DDLOCK_READONLY, NULL);
1248 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
1249 ok(lock.lpSurface == (void *)0xdeadbeef, "Got unexpected lock.lpSurface %p.\n", lock.lpSurface);
1251 hr = restore_surfaces(ddraw);
1252 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1254 hr = IDirectDrawSurface_Lock(rt, NULL, &lock, DDLOCK_READONLY, NULL);
1255 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1256 hr = IDirectDrawSurface2_Unlock(rt, NULL);
1257 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1259 memset(&material, 0, sizeof(material));
1260 material.dwSize = sizeof(material);
1261 material.diffuse.r = 0.0f;
1262 material.diffuse.g = 1.0f;
1263 material.diffuse.b = 0.0f;
1264 material.diffuse.a = 1.0f;
1265 hr = IDirect3DMaterial_SetMaterial(background, &material);
1266 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1268 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&surface);
1269 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1270 ok(surface == rt, "Got unexpected surface %p.\n", surface);
1271 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1272 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1273 color = get_surface_color(rt, 320, 240);
1274 ok(compare_color(color, 0x0000ff00, 1) || broken(compare_color(color, 0x00000000, 1)),
1275 "Got unexpected color 0x%08x.\n", color);
1277 destroy_viewport(device, viewport);
1278 destroy_material(background);
1279 IDirectDrawSurface_Release(surface);
1280 IDirectDrawSurface_Release(rt);
1281 IDirect3DDevice_Release(device);
1282 IDirectDraw_Release(ddraw);
1283 DestroyWindow(window);
1286 static void test_surface_interface_mismatch(void)
1288 IDirectDraw *ddraw = NULL;
1289 IDirectDrawSurface *surface = NULL, *ds;
1290 IDirectDrawSurface3 *surface3 = NULL;
1291 IDirect3DDevice *device = NULL;
1292 IDirect3DViewport *viewport = NULL;
1293 IDirect3DMaterial *background = NULL;
1294 DDSURFACEDESC surface_desc;
1295 unsigned int color;
1296 DWORD z_depth = 0;
1297 ULONG refcount;
1298 HRESULT hr;
1299 HWND window;
1300 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1302 window = create_window();
1303 ddraw = create_ddraw();
1304 ok(!!ddraw, "Failed to create a ddraw object.\n");
1305 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1307 skip("Failed to create a 3D device, skipping test.\n");
1308 IDirectDraw_Release(ddraw);
1309 DestroyWindow(window);
1310 return;
1312 z_depth = get_device_z_depth(device);
1313 ok(!!z_depth, "Failed to get device z depth.\n");
1314 IDirect3DDevice_Release(device);
1315 device = NULL;
1317 memset(&surface_desc, 0, sizeof(surface_desc));
1318 surface_desc.dwSize = sizeof(surface_desc);
1319 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1320 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1321 surface_desc.dwWidth = 640;
1322 surface_desc.dwHeight = 480;
1324 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1325 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
1327 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1328 if (FAILED(hr))
1330 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
1331 goto cleanup;
1334 memset(&surface_desc, 0, sizeof(surface_desc));
1335 surface_desc.dwSize = sizeof(surface_desc);
1336 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
1337 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1338 surface_desc.dwZBufferBitDepth = z_depth;
1339 surface_desc.dwWidth = 640;
1340 surface_desc.dwHeight = 480;
1341 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1342 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#lx.\n", hr);
1343 if (FAILED(hr))
1344 goto cleanup;
1346 /* Using a different surface interface version still works */
1347 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1348 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#lx.\n", hr);
1349 refcount = IDirectDrawSurface_Release(ds);
1350 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
1351 if (FAILED(hr))
1352 goto cleanup;
1354 /* Here too */
1355 hr = IDirectDrawSurface3_QueryInterface(surface3, &IID_IDirect3DHALDevice, (void **)&device);
1356 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1357 if (FAILED(hr))
1358 goto cleanup;
1360 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1361 viewport = create_viewport(device, 0, 0, 640, 480);
1362 viewport_set_background(device, viewport, background);
1364 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1365 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
1366 color = get_surface_color(surface, 320, 240);
1367 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1369 cleanup:
1370 if (viewport)
1371 destroy_viewport(device, viewport);
1372 if (background)
1373 destroy_material(background);
1374 if (surface3) IDirectDrawSurface3_Release(surface3);
1375 if (surface) IDirectDrawSurface_Release(surface);
1376 if (device) IDirect3DDevice_Release(device);
1377 if (ddraw) IDirectDraw_Release(ddraw);
1378 DestroyWindow(window);
1381 static void test_coop_level_threaded(void)
1383 struct create_window_thread_param p;
1384 IDirectDraw *ddraw;
1385 HRESULT hr;
1387 ddraw = create_ddraw();
1388 ok(!!ddraw, "Failed to create a ddraw object.\n");
1389 create_window_thread(&p);
1391 hr = IDirectDraw_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1392 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
1394 destroy_window_thread(&p);
1395 IDirectDraw_Release(ddraw);
1398 static BOOL compare_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
1400 return mode1->dmPosition.x == mode2->dmPosition.x
1401 && mode1->dmPosition.y == mode2->dmPosition.y
1402 && mode1->dmPelsWidth == mode2->dmPelsWidth
1403 && mode1->dmPelsHeight == mode2->dmPelsHeight;
1406 static void init_format_b5g6r5(DDPIXELFORMAT *format)
1408 format->dwSize = sizeof(*format);
1409 format->dwFlags = DDPF_RGB;
1410 format->dwRGBBitCount = 16;
1411 format->dwRBitMask = 0xf800;
1412 format->dwGBitMask = 0x07e0;
1413 format->dwBBitMask = 0x001f;
1416 static ULONG get_refcount(IUnknown *test_iface)
1418 IUnknown_AddRef(test_iface);
1419 return IUnknown_Release(test_iface);
1422 static void test_viewport_object(void)
1424 IDirect3DViewport *viewport, *another_vp;
1425 IDirectDrawGammaControl *gamma;
1426 IDirect3DViewport2 *viewport2;
1427 IDirect3DViewport3 *viewport3;
1428 IDirect3DDevice *device;
1429 IUnknown *unknown;
1430 IDirectDraw *ddraw;
1431 D3DVIEWPORT2 vp2;
1432 D3DVIEWPORT vp;
1433 IDirect3D *d3d;
1434 HWND window;
1435 HRESULT hr;
1436 ULONG ref;
1437 union
1439 D3DVIEWPORT vp1;
1440 BYTE blob[1024];
1441 } desc;
1443 window = create_window();
1444 ddraw = create_ddraw();
1445 ok(!!ddraw, "Failed to create a ddraw object.\n");
1446 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1448 skip("Failed to create a 3D device, skipping test.\n");
1449 IDirectDraw_Release(ddraw);
1450 DestroyWindow(window);
1451 return;
1454 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
1455 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1456 ref = get_refcount((IUnknown *) d3d);
1457 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1459 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
1460 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1461 ref = get_refcount((IUnknown *)viewport);
1462 ok(ref == 1, "Got unexpected refcount %lu.\n", ref);
1463 ref = get_refcount((IUnknown *)d3d);
1464 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1466 memset(&desc, 0, sizeof(desc));
1467 hr = IDirect3DViewport_GetViewport(viewport, &desc.vp1);
1468 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1469 desc.vp1.dwSize = sizeof(desc.vp1) + 1;
1470 hr = IDirect3DViewport_GetViewport(viewport, &desc.vp1);
1471 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1472 desc.vp1.dwSize = sizeof(desc.vp1) - 1;
1473 hr = IDirect3DViewport_GetViewport(viewport, &desc.vp1);
1474 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1475 desc.vp1.dwSize = sizeof(desc.vp1);
1476 hr = IDirect3DViewport_GetViewport(viewport, &desc.vp1);
1477 ok(hr == D3DERR_VIEWPORTDATANOTSET, "Got unexpected hr %#lx.\n", hr);
1478 ok(desc.vp1.dwSize == sizeof(desc.vp1), "Got unexpected dwSize %lu.\n", desc.vp1.dwSize);
1480 /* E_FAIL return values are returned by Winetestbot Windows NT machines. While not supporting
1481 * newer interfaces is legitimate for old ddraw versions, E_FAIL violates Microsoft's rules
1482 * for QueryInterface, hence the broken() */
1483 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1484 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirectDrawGammaControl, (void **)&gamma);
1485 ok(hr == E_NOINTERFACE || broken(hr == E_FAIL), "Got unexpected hr %#lx.\n", hr);
1486 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1488 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport2, (void **)&viewport2);
1489 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1491 ref = get_refcount((IUnknown *)viewport);
1492 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1493 ref = get_refcount((IUnknown *)viewport2);
1494 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1496 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport3, (void **)&viewport3);
1497 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1499 ref = get_refcount((IUnknown *)viewport);
1500 ok(ref == 3, "Got unexpected refcount %lu.\n", ref);
1501 ref = get_refcount((IUnknown *)viewport3);
1502 ok(ref == 3, "Got unexpected refcount %lu.\n", ref);
1503 IDirect3DViewport3_Release(viewport3);
1505 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IUnknown, (void **)&unknown);
1506 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1507 ref = get_refcount((IUnknown *)viewport);
1508 ok(ref == 3, "Got unexpected refcount %lu.\n", ref);
1509 ref = get_refcount(unknown);
1510 ok(ref == 3, "Got unexpected refcount %lu.\n", ref);
1511 IUnknown_Release(unknown);
1513 hr = IDirect3DDevice_DeleteViewport(device, NULL);
1514 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1516 hr = IDirect3D_CreateViewport(d3d, &another_vp, NULL);
1517 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1519 /* AddViewport(NULL): Segfault */
1520 hr = IDirect3DDevice_AddViewport(device, viewport);
1521 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1522 ref = get_refcount((IUnknown *) viewport);
1523 ok(ref == 3, "Got unexpected refcount %lu.\n", ref);
1524 hr = IDirect3DDevice_AddViewport(device, another_vp);
1525 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1526 ref = get_refcount((IUnknown *) another_vp);
1527 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1529 memset(&vp, 0, sizeof(vp));
1530 vp.dwX = 0;
1531 vp.dwY = 0;
1532 vp.dwWidth = 640;
1533 vp.dwHeight = 480;
1534 vp.dvMinZ = 0.0f;
1535 vp.dvMaxZ = 1.0f;
1536 vp.dvScaleX = vp.dwWidth / 2.0f;
1537 vp.dvScaleY = vp.dwHeight / 2.0f;
1538 vp.dvMaxX = 1.0f;
1539 vp.dvMaxY = 1.0f;
1540 hr = IDirect3DViewport_SetViewport(viewport, &vp);
1541 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1543 vp.dwSize = sizeof(vp);
1544 hr = IDirect3DViewport_SetViewport(viewport, &vp);
1545 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1547 vp2.dwSize = sizeof(vp2);
1548 vp2.dwX = 160;
1549 vp2.dwY = 120;
1550 vp2.dwWidth = 640 - vp2.dwX;
1551 vp2.dwHeight = 480 - vp2.dwY;
1552 vp2.dvClipX = 2.0f;
1553 vp2.dvClipY = -1.75f;
1554 vp2.dvClipWidth = 2.5f;
1555 vp2.dvClipHeight = -1.5f;
1556 vp2.dvMinZ = 0.5f;
1557 vp2.dvMaxZ = 2.0f;
1558 hr = IDirect3DViewport2_SetViewport2(viewport2, &vp2);
1559 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1561 memset(&vp, 0xff, sizeof(vp));
1562 vp.dwSize = sizeof(vp);
1563 hr = IDirect3DViewport2_GetViewport(viewport2, &vp);
1564 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1565 ok(vp.dvMaxX == 4.5f && vp.dvMaxY == -1.75f && vp.dvScaleX == 192.0f
1566 && vp.dvScaleY == -240.0f && vp.dvMinZ == 0.0f && vp.dvMaxZ == 1.0f,
1567 "Got unexpected values %g, %g, %g, %g, %g, %g.\n",
1568 vp.dvMaxX, vp.dvMaxY, vp.dvScaleX, vp.dvScaleY, vp.dvMinZ, vp.dvMaxZ);
1570 vp2.dvClipX = -1.5f;
1571 vp2.dvClipY = 1.75f;
1572 vp2.dvClipWidth = -1.5f;
1573 vp2.dvClipHeight = 2.0f;
1574 vp2.dvMinZ = 2.0f;
1575 vp2.dvMaxZ = 0.5f;
1577 hr = IDirect3DViewport2_SetViewport2(viewport2, &vp2);
1578 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1580 memset(&vp, 0xff, sizeof(vp));
1581 vp.dwSize = sizeof(vp);
1582 hr = IDirect3DViewport2_GetViewport(viewport2, &vp);
1583 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1584 ok(vp.dvMaxX == -3.0f && vp.dvMaxY == 1.75f && vp.dvScaleX == -320.0f
1585 && vp.dvScaleY == 180.0f && vp.dvMinZ == 0.0f && vp.dvMaxZ == 1.0f,
1586 "Got unexpected values %g, %g, %g, %g, %g, %g.\n",
1587 vp.dvMaxX, vp.dvMaxY, vp.dvScaleX, vp.dvScaleY, vp.dvMinZ, vp.dvMaxZ);
1589 vp.dwSize = sizeof(vp);
1590 vp.dvMinZ = 0.5f;
1591 vp.dvMaxZ = 2.0f;
1592 hr = IDirect3DViewport2_SetViewport(viewport2, &vp);
1593 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1595 memset(&vp2, 0xff, sizeof(vp2));
1596 vp2.dwSize = sizeof(vp2);
1597 hr = IDirect3DViewport2_GetViewport2(viewport2, &vp2);
1598 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1599 ok(vp2.dvClipX == 0.75f && vp2.dvClipY == 1.0f && vp2.dvClipWidth == -1.5f
1600 && vp2.dvClipHeight == 2.0f && vp2.dvMinZ == 0.0f && vp2.dvMaxZ == 1.0f,
1601 "Got unexpected values %g, %g, %g, %g, %g, %g.\n",
1602 vp2.dvClipX, vp2.dvClipY, vp2.dvClipWidth, vp2.dvClipHeight, vp2.dvMinZ, vp2.dvMaxZ);
1604 vp.dvMaxX = 4.5f;
1605 vp.dvMaxY = -1.75f;
1606 vp.dvScaleX = 192.0f;
1607 vp.dvScaleY = -240.0f;
1608 vp.dvMinZ = 2.0f;
1609 vp.dvMaxZ = 0.5f;
1611 hr = IDirect3DViewport3_SetViewport(viewport3, &vp);
1612 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1614 memset(&vp2, 0xff, sizeof(vp2));
1615 vp2.dwSize = sizeof(vp2);
1616 hr = IDirect3DViewport2_GetViewport2(viewport2, &vp2);
1617 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1618 ok(vp2.dvClipX == -1.25f && vp2.dvClipY == -0.75f && vp2.dvClipWidth == 2.5f
1619 && vp2.dvClipHeight == -1.5f && vp2.dvMinZ == 0.0f && vp2.dvMaxZ == 1.0f,
1620 "Got unexpected values %g, %g, %g, %g, %g, %g.\n",
1621 vp2.dvClipX, vp2.dvClipY, vp2.dvClipWidth, vp2.dvClipHeight, vp2.dvMinZ, vp2.dvMaxZ);
1623 IDirect3DViewport2_Release(viewport2);
1625 hr = IDirect3DDevice_DeleteViewport(device, another_vp);
1626 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1627 ref = get_refcount((IUnknown *) another_vp);
1628 ok(ref == 1, "Got unexpected refcount %lu.\n", ref);
1630 IDirect3DDevice_Release(device);
1631 ref = get_refcount((IUnknown *) viewport);
1632 ok(ref == 1, "Got unexpected refcount %lu.\n", ref);
1634 hr = IDirect3DViewport_SetViewport(viewport, &vp);
1635 ok(hr == D3DERR_VIEWPORTHASNODEVICE, "Got unexpected hr %#lx.\n", hr);
1637 IDirect3DViewport_Release(another_vp);
1638 IDirect3D_Release(d3d);
1639 IDirect3DViewport_Release(viewport);
1640 DestroyWindow(window);
1641 IDirectDraw_Release(ddraw);
1644 static void test_zenable(const GUID *device_guid)
1646 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1647 static D3DTLVERTEX tquad[] =
1649 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1650 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1651 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1652 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1654 unsigned int inst_length, color, x, y, i, j;
1655 IDirect3DExecuteBuffer *execute_buffer;
1656 D3DEXECUTEBUFFERDESC exec_desc;
1657 IDirect3DMaterial *background;
1658 IDirect3DViewport *viewport;
1659 IDirect3DDevice *device;
1660 IDirectDrawSurface *rt;
1661 IDirectDraw *ddraw;
1662 HWND window;
1663 HRESULT hr;
1664 void *ptr;
1666 window = create_window();
1667 ddraw = create_ddraw();
1668 ok(!!ddraw, "Failed to create a ddraw object.\n");
1669 if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid)))
1671 skip("Failed to create a 3D device, skipping test.\n");
1672 IDirectDraw_Release(ddraw);
1673 DestroyWindow(window);
1674 return;
1677 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1678 viewport = create_viewport(device, 0, 0, 640, 480);
1679 viewport_set_background(device, viewport, background);
1681 memset(&exec_desc, 0, sizeof(exec_desc));
1682 exec_desc.dwSize = sizeof(exec_desc);
1683 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1684 exec_desc.dwBufferSize = 1024;
1685 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1687 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1688 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#lx.\n", hr);
1689 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1690 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#lx.\n", hr);
1691 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1692 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1693 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1694 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1695 emit_tquad(&ptr, 0);
1696 emit_end(&ptr);
1697 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
1698 inst_length -= sizeof(tquad);
1699 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1700 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1702 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1703 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1704 hr = IDirect3DDevice_BeginScene(device);
1705 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1706 set_execute_data(execute_buffer, 4, sizeof(tquad), inst_length);
1707 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1708 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1709 hr = IDirect3DDevice_EndScene(device);
1710 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1712 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1713 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1714 for (i = 0; i < 4; ++i)
1716 for (j = 0; j < 4; ++j)
1718 x = 80 * ((2 * j) + 1);
1719 y = 60 * ((2 * i) + 1);
1720 color = get_surface_color(rt, x, y);
1721 ok(compare_color(color, 0x0000ff00, 1),
1722 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1725 IDirectDrawSurface_Release(rt);
1727 destroy_viewport(device, viewport);
1728 IDirect3DExecuteBuffer_Release(execute_buffer);
1729 destroy_material(background);
1730 IDirect3DDevice_Release(device);
1731 IDirectDraw_Release(ddraw);
1732 DestroyWindow(window);
1735 static void test_ck_rgba(const GUID *device_guid)
1737 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1738 static D3DTLVERTEX tquad[] =
1740 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1741 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1742 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1743 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1744 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1745 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1746 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1747 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1749 /* Supposedly there was no D3DRENDERSTATE_COLORKEYENABLE in D3D < 5.
1750 * Maybe the WARP driver on Windows 8 ignores setting it via the older
1751 * device interface but it's buggy in that the internal state is not
1752 * initialized, or possibly toggling D3DRENDERSTATE_COLORKEYENABLE /
1753 * D3DRENDERSTATE_ALPHABLENDENABLE has unintended side effects.
1754 * Checking the W8 test results it seems like test 1 fails most of the time
1755 * and test 0 fails very rarely. */
1756 static const struct
1758 D3DCOLOR fill_color;
1759 BOOL color_key;
1760 BOOL blend;
1761 unsigned int result1, result1_r200, result1_warp;
1762 unsigned int result2, result2_r200, result2_warp;
1764 tests[] =
1766 /* r200 on Windows doesn't check the alpha component when applying the color
1767 * key, so the key matches on every texel. */
1768 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x0000ff00,
1769 0x000000ff, 0x000000ff, 0x0000ff00},
1770 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x0000ff00,
1771 0x000000ff, 0x000000ff, 0x0000ff00},
1772 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1773 0x0000ff00, 0x0000ff00, 0x0000ff00},
1774 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1775 0x0000ff00, 0x0000ff00, 0x0000ff00},
1776 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00,
1777 0x00807f00, 0x000000ff, 0x00807f00},
1778 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00,
1779 0x0000ff00, 0x000000ff, 0x0000ff00},
1780 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00,
1781 0x00807f00, 0x00807f00, 0x00807f00},
1782 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1783 0x0000ff00, 0x0000ff00, 0x0000ff00},
1786 IDirect3DExecuteBuffer *execute_buffer;
1787 D3DTEXTUREHANDLE texture_handle;
1788 D3DEXECUTEBUFFERDESC exec_desc;
1789 IDirect3DMaterial *background;
1790 IDirectDrawSurface *surface;
1791 IDirect3DViewport *viewport;
1792 DDSURFACEDESC surface_desc;
1793 IDirect3DTexture *texture;
1794 IDirect3DDevice *device;
1795 IDirectDrawSurface *rt;
1796 unsigned int color, i;
1797 IDirectDraw *ddraw;
1798 HWND window;
1799 DDBLTFX fx;
1800 HRESULT hr;
1802 window = create_window();
1803 ddraw = create_ddraw();
1804 ok(!!ddraw, "Failed to create a ddraw object.\n");
1805 if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid)))
1807 skip("Failed to create a 3D device, skipping test.\n");
1808 IDirectDraw_Release(ddraw);
1809 DestroyWindow(window);
1810 return;
1813 background = create_diffuse_material(device, 1.0, 0.0f, 0.0f, 1.0f);
1814 viewport = create_viewport(device, 0, 0, 640, 480);
1815 viewport_set_background(device, viewport, background);
1817 memset(&surface_desc, 0, sizeof(surface_desc));
1818 surface_desc.dwSize = sizeof(surface_desc);
1819 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1820 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1821 if (is_software_device_type(device_guid))
1822 surface_desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
1823 surface_desc.dwWidth = 256;
1824 surface_desc.dwHeight = 256;
1825 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1826 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1827 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
1828 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
1829 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
1830 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
1831 surface_desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
1832 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1833 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1834 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1835 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1836 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1837 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1838 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1839 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1840 IDirect3DTexture_Release(texture);
1842 memset(&exec_desc, 0, sizeof(exec_desc));
1843 exec_desc.dwSize = sizeof(exec_desc);
1844 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1845 exec_desc.dwBufferSize = 1024;
1846 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1847 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1848 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1850 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1851 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1853 for (i = 0; i < ARRAY_SIZE(tests); ++i)
1855 UINT draw1_len, draw2_len;
1856 void *ptr;
1858 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1859 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1860 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1861 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1862 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
1863 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1864 emit_set_rs(&ptr, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1865 emit_set_rs(&ptr, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1866 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1868 if (is_software_device_type(device_guid))
1870 /* It looks like D3DRENDERSTATE_COLORKEYENABLE is ignored with software device
1871 * on Windows and the colour key is always enabled if set on surface. */
1872 IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, tests[i].color_key
1873 ? &surface_desc.ddckCKSrcBlt : NULL);
1876 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1877 emit_tquad(&ptr, 0);
1878 emit_end(&ptr);
1879 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - sizeof(tquad);
1880 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 4, 4);
1881 emit_tquad(&ptr, 0);
1882 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1883 emit_end(&ptr);
1884 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_len;
1885 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1886 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1888 memset(&fx, 0, sizeof(fx));
1889 fx.dwSize = sizeof(fx);
1890 fx.dwFillColor = tests[i].fill_color;
1891 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1892 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1894 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1895 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1896 /* RT clears are broken on Windows for software render target. */
1897 if (is_software_device_type(device_guid))
1898 fill_surface(rt, 0xffff0000);
1900 hr = IDirect3DDevice_BeginScene(device);
1901 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1902 set_execute_data(execute_buffer, 8, sizeof(tquad), draw1_len);
1903 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1904 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1905 hr = IDirect3DDevice_EndScene(device);
1906 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1908 color = get_surface_color(rt, 320, 240);
1909 ok(compare_color(color, tests[i].result1, 2)
1910 || broken(compare_color(color, tests[i].result1_r200, 1))
1911 || broken(compare_color(color, tests[i].result1_warp, 1)),
1912 "Got unexpected color 0x%08x for test %u.\n", color, i);
1914 fx.dwFillColor = 0xff0000ff;
1915 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1916 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1918 hr = IDirect3DDevice_BeginScene(device);
1919 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1920 set_execute_data(execute_buffer, 8, sizeof(tquad) + draw1_len, draw2_len);
1921 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1922 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1923 hr = IDirect3DDevice_EndScene(device);
1924 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1926 /* This tests that fragments that are masked out by the color key are
1927 * discarded, instead of just fully transparent. */
1928 color = get_surface_color(rt, 320, 240);
1929 ok(compare_color(color, tests[i].result2, 2)
1930 || broken(compare_color(color, tests[i].result2_r200, 1))
1931 || broken(compare_color(color, tests[i].result2_warp, 1)),
1932 "Got unexpected color 0x%08x for test %u.\n", color, i);
1935 IDirectDrawSurface_Release(rt);
1936 IDirect3DExecuteBuffer_Release(execute_buffer);
1937 IDirectDrawSurface_Release(surface);
1938 destroy_viewport(device, viewport);
1939 destroy_material(background);
1940 IDirect3DDevice_Release(device);
1941 IDirectDraw_Release(ddraw);
1942 DestroyWindow(window);
1945 static void test_ck_default(void)
1947 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1948 static D3DTLVERTEX tquad[] =
1950 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1951 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1952 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1953 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1955 IDirect3DExecuteBuffer *execute_buffer;
1956 IDirectDrawSurface *surface, *rt;
1957 D3DTEXTUREHANDLE texture_handle;
1958 D3DEXECUTEBUFFERDESC exec_desc;
1959 IDirect3DMaterial *background;
1960 UINT draw1_offset, draw1_len;
1961 UINT draw2_offset, draw2_len;
1962 UINT draw3_offset, draw3_len;
1963 UINT draw4_offset, draw4_len;
1964 IDirect3DViewport *viewport;
1965 DDSURFACEDESC surface_desc;
1966 IDirect3DTexture *texture;
1967 IDirect3DDevice *device;
1968 unsigned int color;
1969 IDirectDraw *ddraw;
1970 HWND window;
1971 DDBLTFX fx;
1972 HRESULT hr;
1973 void *ptr;
1975 window = create_window();
1976 ddraw = create_ddraw();
1977 ok(!!ddraw, "Failed to create a ddraw object.\n");
1978 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1980 skip("Failed to create a 3D device, skipping test.\n");
1981 IDirectDraw_Release(ddraw);
1982 DestroyWindow(window);
1983 return;
1986 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1987 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
1989 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
1990 viewport = create_viewport(device, 0, 0, 640, 480);
1991 viewport_set_background(device, viewport, background);
1993 memset(&surface_desc, 0, sizeof(surface_desc));
1994 surface_desc.dwSize = sizeof(surface_desc);
1995 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1996 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1997 surface_desc.dwWidth = 256;
1998 surface_desc.dwHeight = 256;
1999 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
2000 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
2001 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
2002 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
2003 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
2004 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
2005 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
2006 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
2007 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2008 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
2009 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
2010 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
2011 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
2012 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#lx.\n", hr);
2013 IDirect3DTexture_Release(texture);
2015 memset(&fx, 0, sizeof(fx));
2016 fx.dwSize = sizeof(fx);
2017 fx.dwFillColor = 0x000000ff;
2018 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
2019 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#lx.\n", hr);
2021 memset(&exec_desc, 0, sizeof(exec_desc));
2022 exec_desc.dwSize = sizeof(exec_desc);
2023 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
2024 exec_desc.dwBufferSize = 1024;
2025 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
2026 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
2027 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#lx.\n", hr);
2029 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
2030 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#lx.\n", hr);
2031 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
2032 ptr = (BYTE *)exec_desc.lpData + sizeof(tquad);
2033 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
2034 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
2035 emit_tquad(&ptr, 0);
2036 emit_end(&ptr);
2037 draw1_offset = sizeof(tquad);
2038 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_offset;
2039 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
2040 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, FALSE);
2041 emit_tquad(&ptr, 0);
2042 emit_end(&ptr);
2043 draw2_offset = draw1_offset + draw1_len;
2044 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw2_offset;
2045 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
2046 emit_tquad(&ptr, 0);
2047 emit_end(&ptr);
2048 draw3_offset = draw2_offset + draw2_len;
2049 draw3_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw3_offset;
2050 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
2051 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
2052 emit_tquad(&ptr, 0);
2053 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
2054 emit_end(&ptr);
2055 draw4_offset = draw3_offset + draw3_len;
2056 draw4_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw4_offset;
2057 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
2058 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#lx.\n", hr);
2060 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2061 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
2062 hr = IDirect3DDevice_BeginScene(device);
2063 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
2064 set_execute_data(execute_buffer, 4, draw1_offset, draw1_len);
2065 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
2066 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#lx.\n", hr);
2067 hr = IDirect3DDevice_EndScene(device);
2068 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
2069 color = get_surface_color(rt, 320, 240);
2070 /* Color keying is supposed to be on by default in ddraw1, but used only if a ckey is set.
2071 * WARP begs to differ. The default of D3DRENDERSTATE_COLORKEYENABLE is random, and it
2072 * doesn't mind the absence of a color key (the latter part affects other tests, not this one). */
2073 ok(compare_color(color, 0x0000ff00, 1) || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x000000ff, 1)),
2074 "Got unexpected color 0x%08x.\n", color);
2076 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2077 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
2078 hr = IDirect3DDevice_BeginScene(device);
2079 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
2080 set_execute_data(execute_buffer, 4, draw2_offset, draw2_len);
2081 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
2082 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#lx.\n", hr);
2083 hr = IDirect3DDevice_EndScene(device);
2084 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
2085 color = get_surface_color(rt, 320, 240);
2086 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
2088 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2089 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
2090 hr = IDirect3DDevice_BeginScene(device);
2091 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
2092 set_execute_data(execute_buffer, 4, draw3_offset, draw3_len);
2093 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
2094 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#lx.\n", hr);
2095 hr = IDirect3DDevice_EndScene(device);
2096 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
2097 color = get_surface_color(rt, 320, 240);
2098 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
2100 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2101 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
2102 hr = IDirect3DDevice_BeginScene(device);
2103 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
2104 set_execute_data(execute_buffer, 4, draw4_offset, draw4_len);
2105 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
2106 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#lx.\n", hr);
2107 hr = IDirect3DDevice_EndScene(device);
2108 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
2109 color = get_surface_color(rt, 320, 240);
2110 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
2112 IDirect3DExecuteBuffer_Release(execute_buffer);
2113 IDirectDrawSurface_Release(surface);
2114 destroy_viewport(device, viewport);
2115 destroy_material(background);
2116 IDirectDrawSurface_Release(rt);
2117 IDirect3DDevice_Release(device);
2118 IDirectDraw_Release(ddraw);
2119 DestroyWindow(window);
2122 static void test_ck_complex(void)
2124 IDirectDrawSurface *surface, *mipmap, *tmp;
2125 DDSCAPS caps = {DDSCAPS_COMPLEX};
2126 DDSURFACEDESC surface_desc;
2127 IDirect3DDevice *device;
2128 DDCOLORKEY color_key;
2129 IDirectDraw *ddraw;
2130 unsigned int i;
2131 ULONG refcount;
2132 HWND window;
2133 HRESULT hr;
2135 window = create_window();
2136 ddraw = create_ddraw();
2137 ok(!!ddraw, "Failed to create a ddraw object.\n");
2138 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
2140 skip("Failed to create a 3D device, skipping test.\n");
2141 DestroyWindow(window);
2142 IDirectDraw_Release(ddraw);
2143 return;
2145 IDirect3DDevice_Release(device);
2147 memset(&surface_desc, 0, sizeof(surface_desc));
2148 surface_desc.dwSize = sizeof(surface_desc);
2149 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2150 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2151 surface_desc.dwWidth = 128;
2152 surface_desc.dwHeight = 128;
2153 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2154 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
2156 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2157 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx.\n", hr);
2158 color_key.dwColorSpaceLowValue = 0x0000ff00;
2159 color_key.dwColorSpaceHighValue = 0x0000ff00;
2160 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2161 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
2162 memset(&color_key, 0, sizeof(color_key));
2163 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2164 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
2165 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2166 color_key.dwColorSpaceLowValue);
2167 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2168 color_key.dwColorSpaceHighValue);
2170 mipmap = surface;
2171 IDirectDrawSurface_AddRef(mipmap);
2172 for (i = 0; i < 7; ++i)
2174 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
2175 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#lx.\n", i, hr);
2177 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2178 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx, i %u.\n", hr, i);
2179 color_key.dwColorSpaceLowValue = 0x000000ff;
2180 color_key.dwColorSpaceHighValue = 0x000000ff;
2181 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2182 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx, i %u.\n", hr, i);
2183 memset(&color_key, 0, sizeof(color_key));
2184 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2185 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx, i %u.\n", hr, i);
2186 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08lx, i %u.\n",
2187 color_key.dwColorSpaceLowValue, i);
2188 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08lx, i %u.\n",
2189 color_key.dwColorSpaceHighValue, i);
2191 IDirectDrawSurface_Release(mipmap);
2192 mipmap = tmp;
2195 memset(&color_key, 0, sizeof(color_key));
2196 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2197 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
2198 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2199 color_key.dwColorSpaceLowValue);
2200 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2201 color_key.dwColorSpaceHighValue);
2203 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
2204 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
2205 IDirectDrawSurface_Release(mipmap);
2206 refcount = IDirectDrawSurface_Release(surface);
2207 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
2209 memset(&surface_desc, 0, sizeof(surface_desc));
2210 surface_desc.dwSize = sizeof(surface_desc);
2211 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
2212 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
2213 surface_desc.dwBackBufferCount = 1;
2214 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2215 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
2217 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2218 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx.\n", hr);
2219 color_key.dwColorSpaceLowValue = 0x0000ff00;
2220 color_key.dwColorSpaceHighValue = 0x0000ff00;
2221 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2222 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
2223 memset(&color_key, 0, sizeof(color_key));
2224 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2225 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
2226 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2227 color_key.dwColorSpaceLowValue);
2228 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2229 color_key.dwColorSpaceHighValue);
2231 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
2232 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#lx.\n", hr);
2234 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2235 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx, i %u.\n", hr, i);
2236 color_key.dwColorSpaceLowValue = 0x0000ff00;
2237 color_key.dwColorSpaceHighValue = 0x0000ff00;
2238 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2239 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
2240 memset(&color_key, 0, sizeof(color_key));
2241 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2242 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
2243 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2244 color_key.dwColorSpaceLowValue);
2245 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2246 color_key.dwColorSpaceHighValue);
2248 IDirectDrawSurface_Release(tmp);
2250 refcount = IDirectDrawSurface_Release(surface);
2251 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
2252 refcount = IDirectDraw_Release(ddraw);
2253 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
2254 DestroyWindow(window);
2257 struct qi_test
2259 REFIID iid;
2260 REFIID refcount_iid;
2261 HRESULT hr;
2264 static void test_qi(const char *test_name, IUnknown *base_iface,
2265 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
2267 ULONG refcount, expected_refcount;
2268 IUnknown *iface1, *iface2;
2269 HRESULT hr;
2270 UINT i, j;
2272 for (i = 0; i < entry_count; ++i)
2274 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
2275 ok(hr == tests[i].hr, "Got hr %#lx for test \"%s\" %u.\n", hr, test_name, i);
2276 if (SUCCEEDED(hr))
2278 for (j = 0; j < entry_count; ++j)
2280 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
2281 ok(hr == tests[j].hr, "Got hr %#lx for test \"%s\" %u, %u.\n", hr, test_name, i, j);
2282 if (SUCCEEDED(hr))
2284 expected_refcount = 0;
2285 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
2286 ++expected_refcount;
2287 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
2288 ++expected_refcount;
2289 refcount = IUnknown_Release(iface2);
2290 ok(refcount == expected_refcount, "Got refcount %lu for test \"%s\" %u, %u, expected %lu.\n",
2291 refcount, test_name, i, j, expected_refcount);
2295 expected_refcount = 0;
2296 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
2297 ++expected_refcount;
2298 refcount = IUnknown_Release(iface1);
2299 ok(refcount == expected_refcount, "Got refcount %lu for test \"%s\" %u, expected %lu.\n",
2300 refcount, test_name, i, expected_refcount);
2305 static void test_surface_qi(void)
2307 static const struct qi_test tests[] =
2309 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
2310 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
2311 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
2312 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2313 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
2314 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
2315 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
2316 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
2317 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
2318 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
2319 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
2320 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
2321 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
2322 {&IID_IDirect3D7, NULL, E_INVALIDARG },
2323 {&IID_IDirect3D3, NULL, E_INVALIDARG },
2324 {&IID_IDirect3D2, NULL, E_INVALIDARG },
2325 {&IID_IDirect3D, NULL, E_INVALIDARG },
2326 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
2327 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
2328 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
2329 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
2330 {&IID_IDirectDraw, NULL, E_INVALIDARG },
2331 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
2332 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
2333 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
2334 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
2335 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
2336 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
2337 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
2338 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
2339 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
2340 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
2341 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
2342 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
2343 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
2344 {NULL, NULL, E_INVALIDARG },
2347 IDirectDrawSurface *surface;
2348 DDSURFACEDESC surface_desc;
2349 IDirect3DDevice *device;
2350 IDirectDraw *ddraw;
2351 HWND window;
2352 HRESULT hr;
2354 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
2356 win_skip("DirectDrawCreateEx not available, skipping test.\n");
2357 return;
2360 window = create_window();
2361 ddraw = create_ddraw();
2362 ok(!!ddraw, "Failed to create a ddraw object.\n");
2363 /* Try to create a D3D device to see if the ddraw implementation supports
2364 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
2365 * doesn't support e.g. the IDirect3DTexture interfaces. */
2366 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2368 skip("Failed to create a 3D device, skipping test.\n");
2369 IDirectDraw_Release(ddraw);
2370 DestroyWindow(window);
2371 return;
2373 IDirect3DDevice_Release(device);
2375 memset(&surface_desc, 0, sizeof(surface_desc));
2376 surface_desc.dwSize = sizeof(surface_desc);
2377 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2378 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2379 surface_desc.dwWidth = 512;
2380 surface_desc.dwHeight = 512;
2381 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, (IDirectDrawSurface **)0xdeadbeef, NULL);
2382 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
2383 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2384 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
2386 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, ARRAY_SIZE(tests));
2388 IDirectDrawSurface_Release(surface);
2389 IDirectDraw_Release(ddraw);
2390 DestroyWindow(window);
2393 static void test_device_qi(void)
2395 static const struct qi_test tests[] =
2397 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
2398 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
2399 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
2400 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2401 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
2402 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
2403 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
2404 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
2405 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
2406 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
2407 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
2408 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
2409 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
2410 {&IID_IDirect3DHALDevice, &IID_IDirectDrawSurface, S_OK },
2411 {&IID_IDirect3D7, NULL, E_INVALIDARG },
2412 {&IID_IDirect3D3, NULL, E_INVALIDARG },
2413 {&IID_IDirect3D2, NULL, E_INVALIDARG },
2414 {&IID_IDirect3D, NULL, E_INVALIDARG },
2415 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
2416 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
2417 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
2418 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
2419 {&IID_IDirectDraw, NULL, E_INVALIDARG },
2420 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
2421 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
2422 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
2423 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
2424 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
2425 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
2426 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
2427 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
2428 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
2429 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
2430 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
2431 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
2432 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
2436 IDirect3DDevice *device;
2437 IDirectDraw *ddraw;
2438 HWND window;
2440 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
2442 win_skip("DirectDrawCreateEx not available, skipping test.\n");
2443 return;
2446 window = create_window();
2447 ddraw = create_ddraw();
2448 ok(!!ddraw, "Failed to create a ddraw object.\n");
2449 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2451 skip("Failed to create a 3D device, skipping test.\n");
2452 IDirectDraw_Release(ddraw);
2453 DestroyWindow(window);
2454 return;
2457 test_qi("device_qi", (IUnknown *)device, &IID_IDirectDrawSurface, tests, ARRAY_SIZE(tests));
2459 IDirect3DDevice_Release(device);
2460 IDirectDraw_Release(ddraw);
2461 DestroyWindow(window);
2464 static void test_wndproc(void)
2466 LONG_PTR proc, ddraw_proc;
2467 IDirectDraw *ddraw;
2468 WNDCLASSA wc = {0};
2469 HWND window;
2470 HRESULT hr;
2471 ULONG ref;
2473 static struct message messages[] =
2475 {WM_WINDOWPOSCHANGING, FALSE, 0},
2476 {WM_MOVE, FALSE, 0},
2477 {WM_SIZE, FALSE, 0},
2478 {WM_WINDOWPOSCHANGING, FALSE, 0},
2479 {WM_ACTIVATE, FALSE, 0},
2480 {WM_SETFOCUS, FALSE, 0},
2481 {0, FALSE, 0},
2484 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2485 ddraw = create_ddraw();
2486 ok(!!ddraw, "Failed to create a ddraw object.\n");
2488 wc.lpfnWndProc = test_proc;
2489 wc.lpszClassName = "ddraw_test_wndproc_wc";
2490 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2492 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2493 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2495 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2496 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2497 (LONG_PTR)test_proc, proc);
2498 expect_messages = messages;
2499 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2500 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2501 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2502 expect_messages = NULL;
2503 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2504 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix, got %#Ix.\n",
2505 (LONG_PTR)test_proc, proc);
2506 ref = IDirectDraw_Release(ddraw);
2507 ok(!ref, "Unexpected refcount %lu.\n", ref);
2508 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2509 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2510 (LONG_PTR)test_proc, proc);
2512 /* DDSCL_NORMAL doesn't. */
2513 ddraw = create_ddraw();
2514 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2515 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2516 (LONG_PTR)test_proc, proc);
2517 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2518 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2519 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2520 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2521 (LONG_PTR)test_proc, proc);
2522 ref = IDirectDraw_Release(ddraw);
2523 ok(!ref, "Unexpected refcount %lu.\n", ref);
2524 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2525 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2526 (LONG_PTR)test_proc, proc);
2528 /* The original window proc is only restored by ddraw if the current
2529 * window proc matches the one ddraw set. This also affects switching
2530 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2531 ddraw = create_ddraw();
2532 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2533 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2534 (LONG_PTR)test_proc, proc);
2535 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2536 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2537 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2538 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix, got %#Ix.\n",
2539 (LONG_PTR)test_proc, proc);
2540 ddraw_proc = proc;
2541 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2542 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2543 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2544 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2545 (LONG_PTR)test_proc, proc);
2546 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2547 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2548 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2549 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix, got %#Ix.\n",
2550 (LONG_PTR)test_proc, proc);
2551 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2552 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2553 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2554 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#Ix, got %#Ix.\n",
2555 (LONG_PTR)DefWindowProcA, proc);
2556 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2557 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2558 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, ddraw_proc);
2559 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#Ix, got %#Ix.\n",
2560 (LONG_PTR)DefWindowProcA, proc);
2561 ref = IDirectDraw_Release(ddraw);
2562 ok(!ref, "Unexpected refcount %lu.\n", ref);
2563 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2564 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2565 (LONG_PTR)test_proc, proc);
2567 ddraw = create_ddraw();
2568 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2569 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2570 (LONG_PTR)test_proc, proc);
2571 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2572 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2573 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2574 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix, got %#Ix.\n",
2575 (LONG_PTR)test_proc, proc);
2576 ref = IDirectDraw_Release(ddraw);
2577 ok(!ref, "Unexpected refcount %lu.\n", ref);
2578 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2579 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#Ix, got %#Ix.\n",
2580 (LONG_PTR)DefWindowProcA, proc);
2582 fix_wndproc(window, (LONG_PTR)test_proc);
2583 expect_messages = NULL;
2584 DestroyWindow(window);
2585 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2588 static void test_window_style(void)
2590 LONG style, exstyle, tmp, expected_style;
2591 RECT fullscreen_rect, r;
2592 HWND window, window2;
2593 IDirectDraw *ddraw;
2594 HRESULT hr;
2595 ULONG ref;
2596 BOOL ret;
2598 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2599 0, 0, 100, 100, 0, 0, 0, 0);
2600 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2601 0, 0, 50, 50, 0, 0, 0, 0);
2602 ddraw = create_ddraw();
2603 ok(!!ddraw, "Failed to create a ddraw object.\n");
2605 style = GetWindowLongA(window, GWL_STYLE);
2606 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2607 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2609 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2610 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2612 tmp = GetWindowLongA(window, GWL_STYLE);
2613 todo_wine ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2614 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2615 todo_wine ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2617 GetWindowRect(window, &r);
2618 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2619 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2620 GetClientRect(window, &r);
2621 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2623 ret = SetForegroundWindow(GetDesktopWindow());
2624 ok(ret, "Failed to set foreground window.\n");
2626 tmp = GetWindowLongA(window, GWL_STYLE);
2627 todo_wine ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2628 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2629 todo_wine ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2631 ret = SetForegroundWindow(window);
2632 ok(ret, "Failed to set foreground window.\n");
2633 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2634 * the next tests expect this. */
2635 ShowWindow(window, SW_HIDE);
2637 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2638 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2640 tmp = GetWindowLongA(window, GWL_STYLE);
2641 ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2642 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2643 ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2645 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_NOWINDOWCHANGES);
2646 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2648 tmp = GetWindowLongA(window, GWL_STYLE);
2649 todo_wine ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2650 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2651 todo_wine ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2653 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2654 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2656 tmp = GetWindowLongA(window, GWL_STYLE);
2657 expected_style = style | WS_VISIBLE;
2658 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
2659 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2660 expected_style = exstyle | WS_EX_TOPMOST;
2661 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2663 ShowWindow(window, SW_HIDE);
2664 tmp = GetWindowLongA(window, GWL_STYLE);
2665 todo_wine ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2666 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2667 expected_style = exstyle | WS_EX_TOPMOST;
2668 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2670 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_NOWINDOWCHANGES);
2671 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2673 tmp = GetWindowLongA(window, GWL_STYLE);
2674 ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2675 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2676 expected_style = exstyle | WS_EX_TOPMOST;
2677 ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2679 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2680 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2682 tmp = GetWindowLongA(window, GWL_STYLE);
2683 ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2684 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2685 expected_style = exstyle | WS_EX_TOPMOST;
2686 ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2688 ret = SetForegroundWindow(window);
2689 ok(ret, "Failed to set foreground window.\n");
2691 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2692 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2694 tmp = GetWindowLongA(window, GWL_STYLE);
2695 expected_style = style | WS_VISIBLE;
2696 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
2697 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2698 expected_style = exstyle | WS_EX_TOPMOST;
2699 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2701 ShowWindow(window, SW_HIDE);
2702 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2703 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2705 tmp = GetWindowLongA(window, GWL_STYLE);
2706 ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2707 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2708 ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2710 ShowWindow(window, SW_SHOW);
2711 ret = SetForegroundWindow(GetDesktopWindow());
2712 ok(ret, "Failed to set foreground window.\n");
2713 SetActiveWindow(window);
2714 ok(GetActiveWindow() == window, "Unexpected active window.\n");
2715 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2716 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2718 tmp = GetWindowLongA(window, GWL_STYLE);
2719 expected_style = style | WS_VISIBLE;
2720 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
2721 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2722 todo_wine ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2724 GetWindowRect(window, &r);
2725 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2726 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2728 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2729 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2731 SetWindowPos(window, NULL, 0, 0, 100, 100, SWP_NOZORDER | SWP_NOACTIVATE);
2732 GetWindowRect(window, &r);
2733 ok(!EqualRect(&r, &fullscreen_rect), "Window resize failed? got %s.\n",
2734 wine_dbgstr_rect(&r));
2736 ret = SetForegroundWindow(window2);
2737 ok(ret, "Failed to set foreground window.\n");
2738 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2739 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2741 tmp = GetWindowLongA(window, GWL_STYLE);
2742 expected_style = style | WS_VISIBLE;
2743 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
2744 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2745 todo_wine ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2747 GetWindowRect(window, &r);
2748 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2749 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2751 ret = SetForegroundWindow(window);
2752 ok(ret, "Failed to set foreground window.\n");
2753 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2754 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2756 tmp = GetWindowLongA(window, GWL_STYLE);
2757 expected_style = style | WS_VISIBLE;
2758 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
2759 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2760 expected_style = exstyle | WS_EX_TOPMOST;
2761 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2763 ShowWindow(window, SW_HIDE);
2764 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2765 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2767 tmp = GetWindowLongA(window, GWL_STYLE);
2768 ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2769 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2770 ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2772 ShowWindow(window, SW_SHOW);
2773 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2774 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2776 tmp = GetWindowLongA(window, GWL_STYLE);
2777 expected_style = style | WS_VISIBLE;
2778 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
2779 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2780 expected_style = exstyle | WS_EX_TOPMOST;
2781 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2783 ret = SetForegroundWindow(GetDesktopWindow());
2784 ok(ret, "Failed to set foreground window.\n");
2785 tmp = GetWindowLongA(window, GWL_STYLE);
2786 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2787 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
2788 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2789 expected_style = exstyle | WS_EX_TOPMOST;
2790 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2792 /* Test that there is a ~1.5s timer that checks and restores WS_EX_TOPMOST if it's missing */
2793 ret = ShowWindow(window, SW_RESTORE);
2794 ok(ret, "ShowWindow failed, error %#lx.\n", GetLastError());
2795 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2796 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2797 flush_events();
2799 /* Remove WS_VISIBLE and WS_EX_TOPMOST */
2800 tmp = GetWindowLongA(window, GWL_STYLE);
2801 ok(tmp & WS_VISIBLE, "Expected WS_VISIBLE.\n");
2802 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2803 ok(tmp & WS_EX_TOPMOST, "Expected WS_EX_TOPMOST.\n");
2804 ret = ShowWindow(window, SW_HIDE);
2805 ok(ret, "ShowWindow failed, error %#lx.\n", GetLastError());
2806 ret = SetWindowPos(window, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
2807 ok(ret, "SetWindowPos failed, error %#lx.\n", GetLastError());
2808 tmp = GetWindowLongA(window, GWL_STYLE);
2809 ok(!(tmp & WS_VISIBLE), "Got unexpected WS_VISIBLE.\n");
2810 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2811 ok(!(tmp & WS_EX_TOPMOST), "Got unexpected WS_EX_TOPMOST.\n");
2813 Sleep(2000);
2814 flush_events();
2816 /* WS_VISIBLE is not restored but WS_EX_TOPMOST is */
2817 tmp = GetWindowLongA(window, GWL_STYLE);
2818 ok(!(tmp & WS_VISIBLE), "Got unexpected WS_VISIBLE.\n");
2819 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2820 ok(tmp & WS_EX_TOPMOST, "Expected WS_EX_TOPMOST.\n");
2822 ref = IDirectDraw_Release(ddraw);
2823 ok(!ref, "Unexpected refcount %lu.\n", ref);
2825 DestroyWindow(window2);
2826 DestroyWindow(window);
2829 static void test_redundant_mode_set(void)
2831 DDSURFACEDESC surface_desc = {0};
2832 IDirectDraw *ddraw;
2833 RECT q, r, s;
2834 HWND window;
2835 HRESULT hr;
2836 ULONG ref;
2838 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2839 0, 0, 100, 100, 0, 0, 0, 0);
2840 ddraw = create_ddraw();
2841 ok(!!ddraw, "Failed to create a ddraw object.\n");
2843 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2844 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2846 surface_desc.dwSize = sizeof(surface_desc);
2847 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
2848 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#lx.\n", hr);
2850 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2851 surface_desc.ddpfPixelFormat.dwRGBBitCount);
2852 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#lx.\n", hr);
2854 GetWindowRect(window, &q);
2855 r = q;
2856 r.right /= 2;
2857 r.bottom /= 2;
2858 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2859 GetWindowRect(window, &s);
2860 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2862 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2863 surface_desc.ddpfPixelFormat.dwRGBBitCount);
2864 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#lx.\n", hr);
2866 GetWindowRect(window, &s);
2867 ok(EqualRect(&r, &s) || broken(EqualRect(&q, &s) /* Windows 10 */),
2868 "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2870 ref = IDirectDraw_Release(ddraw);
2871 ok(!ref, "Unexpected refcount %lu.\n", ref);
2873 DestroyWindow(window);
2876 static SIZE screen_size;
2878 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2880 if (message == WM_SIZE)
2882 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2883 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2886 return test_proc(hwnd, message, wparam, lparam);
2889 struct test_coop_level_mode_set_enum_param
2891 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2894 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC *surface_desc, void *context)
2896 struct test_coop_level_mode_set_enum_param *param = context;
2898 if (surface_desc->ddpfPixelFormat.dwRGBBitCount != registry_mode.dmBitsPerPel)
2899 return DDENUMRET_OK;
2900 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2901 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2902 return DDENUMRET_OK;
2904 if (!param->ddraw_width)
2906 param->ddraw_width = surface_desc->dwWidth;
2907 param->ddraw_height = surface_desc->dwHeight;
2908 return DDENUMRET_OK;
2910 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2911 return DDENUMRET_OK;
2913 /* The docs say the DDENUMRET_CANCEL below cancels the enumeration, so the check should be
2914 * redundant. However, since Windows 10 this no longer works and the enumeration continues
2915 * until all supported modes are enumerated. Win8 and earlier do cancel.
2917 * Unrelatedly, some testbot machines report high res modes like 1920x1080, but suffer from
2918 * some problems when we actually try to set them (w10pro64 and its localization siblings).
2919 * Try to stay below the registry mode if possible. */
2920 if (!param->user32_width || (surface_desc->dwWidth < registry_mode.dmPelsWidth
2921 && surface_desc->dwHeight < registry_mode.dmPelsHeight))
2923 param->user32_width = surface_desc->dwWidth;
2924 param->user32_height = surface_desc->dwHeight;
2926 return DDENUMRET_CANCEL;
2929 static void test_coop_level_mode_set(void)
2931 DEVMODEW *original_modes = NULL, devmode, devmode2;
2932 unsigned int display_count = 0;
2933 IDirectDrawSurface *primary;
2934 RECT registry_rect, ddraw_rect, user32_rect, r;
2935 IDirectDraw *ddraw;
2936 DDSURFACEDESC ddsd;
2937 WNDCLASSA wc = {0};
2938 HWND window;
2939 HRESULT hr;
2940 ULONG ref;
2941 MSG msg;
2942 struct test_coop_level_mode_set_enum_param param;
2943 BOOL ret;
2944 LONG change_ret;
2946 static const struct message exclusive_messages[] =
2948 {WM_WINDOWPOSCHANGING, FALSE, 0},
2949 {WM_WINDOWPOSCHANGED, FALSE, 0},
2950 {WM_SIZE, FALSE, 0},
2951 {WM_DISPLAYCHANGE, FALSE, 0},
2952 {0, FALSE, 0},
2954 static const struct message exclusive_focus_loss_messages[] =
2956 {WM_ACTIVATE, TRUE, WA_INACTIVE},
2957 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window resize due to mode change. */
2958 {WM_WINDOWPOSCHANGED, FALSE, 0},
2959 {WM_SIZE, TRUE, SIZE_RESTORED}, /* Generated by DefWindowProc. */
2960 {WM_DISPLAYCHANGE, FALSE, 0},
2961 {WM_KILLFOCUS, FALSE, 0},
2962 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window minimized. */
2963 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2964 * SW_MINIMIZED, causing a recursive window activation that does not
2965 * produce the same result in Wine yet. Ignore the difference for now.
2966 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2967 {WM_WINDOWPOSCHANGED, FALSE, 0},
2968 {WM_MOVE, FALSE, 0},
2969 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2970 {WM_ACTIVATEAPP, TRUE, FALSE},
2971 {0, FALSE, 0},
2973 static const struct message exclusive_focus_restore_messages[] =
2975 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2976 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2977 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2978 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2979 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2980 /* Native redundantly sets the window size here. */
2981 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2982 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2983 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2984 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2985 {0, FALSE, 0},
2987 static const struct message sc_restore_messages[] =
2989 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2990 {WM_WINDOWPOSCHANGING, FALSE, 0},
2991 {WM_WINDOWPOSCHANGED, FALSE, 0},
2992 {WM_SIZE, TRUE, SIZE_RESTORED},
2993 {0, FALSE, 0},
2995 static const struct message sc_minimize_messages[] =
2997 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2998 {WM_WINDOWPOSCHANGING, FALSE, 0},
2999 {WM_WINDOWPOSCHANGED, FALSE, 0},
3000 {WM_SIZE, TRUE, SIZE_MINIMIZED},
3001 {0, FALSE, 0},
3003 static const struct message sc_maximize_messages[] =
3005 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
3006 {WM_WINDOWPOSCHANGING, FALSE, 0},
3007 {WM_WINDOWPOSCHANGED, FALSE, 0},
3008 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
3009 {0, FALSE, 0},
3012 static const struct message normal_messages[] =
3014 {WM_DISPLAYCHANGE, FALSE, 0},
3015 {0, FALSE, 0},
3018 memset(&devmode, 0, sizeof(devmode));
3019 devmode.dmSize = sizeof(devmode);
3020 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3021 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3022 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3023 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
3024 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3025 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3027 ret = save_display_modes(&original_modes, &display_count);
3028 ok(ret, "Failed to save original display modes.\n");
3030 ddraw = create_ddraw();
3031 ok(!!ddraw, "Failed to create a ddraw object.\n");
3033 memset(&param, 0, sizeof(param));
3034 hr = IDirectDraw_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
3035 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#lx.\n", hr);
3036 ref = IDirectDraw_Release(ddraw);
3037 ok(!ref, "Unexpected refcount %lu.\n", ref);
3039 if (!param.user32_height)
3041 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
3042 free(original_modes);
3043 return;
3046 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3047 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
3048 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
3050 memset(&devmode, 0, sizeof(devmode));
3051 devmode.dmSize = sizeof(devmode);
3052 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3053 devmode.dmPelsWidth = param.user32_width;
3054 devmode.dmPelsHeight = param.user32_height;
3055 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3056 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3058 ddraw = create_ddraw();
3059 ok(!!ddraw, "Failed to create a ddraw object.\n");
3061 wc.lpfnWndProc = mode_set_proc;
3062 wc.lpszClassName = "ddraw_test_wndproc_wc";
3063 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3065 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
3066 0, 0, 100, 100, 0, 0, 0, 0);
3068 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3069 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3071 GetWindowRect(window, &r);
3072 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
3073 wine_dbgstr_rect(&r));
3075 memset(&ddsd, 0, sizeof(ddsd));
3076 ddsd.dwSize = sizeof(ddsd);
3077 ddsd.dwFlags = DDSD_CAPS;
3078 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3080 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3081 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3082 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3083 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3084 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %lu, got %lu.\n",
3085 param.user32_width, ddsd.dwWidth);
3086 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %lu, got %lu.\n",
3087 param.user32_height, ddsd.dwHeight);
3089 GetWindowRect(window, &r);
3090 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
3091 wine_dbgstr_rect(&r));
3093 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3094 expect_messages = exclusive_messages;
3095 screen_size.cx = 0;
3096 screen_size.cy = 0;
3098 hr = IDirectDrawSurface_IsLost(primary);
3099 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3100 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3101 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3102 hr = IDirectDrawSurface_IsLost(primary);
3103 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3105 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3106 expect_messages = NULL;
3107 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
3108 "Expected screen size %lux%lu, got %lux%lu.\n",
3109 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
3111 GetWindowRect(window, &r);
3112 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3113 wine_dbgstr_rect(&r));
3115 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3116 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3117 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %lu, got %lu.\n",
3118 param.user32_width, ddsd.dwWidth);
3119 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %lu, got %lu.\n",
3120 param.user32_height, ddsd.dwHeight);
3121 IDirectDrawSurface_Release(primary);
3123 memset(&ddsd, 0, sizeof(ddsd));
3124 ddsd.dwSize = sizeof(ddsd);
3125 ddsd.dwFlags = DDSD_CAPS;
3126 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3128 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3129 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3130 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3131 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3132 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3133 param.ddraw_width, ddsd.dwWidth);
3134 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3135 param.ddraw_height, ddsd.dwHeight);
3137 GetWindowRect(window, &r);
3138 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3139 wine_dbgstr_rect(&r));
3141 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3142 expect_messages = exclusive_messages;
3143 screen_size.cx = 0;
3144 screen_size.cy = 0;
3146 hr = IDirectDrawSurface_IsLost(primary);
3147 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3148 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3149 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3150 hr = IDirectDrawSurface_IsLost(primary);
3151 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3153 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3154 expect_messages = NULL;
3155 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
3156 "Expected screen size %lux%lu, got %lux%lu.\n",
3157 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
3159 GetWindowRect(window, &r);
3160 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
3161 wine_dbgstr_rect(&r));
3163 expect_messages = exclusive_focus_loss_messages;
3164 ret = SetForegroundWindow(GetDesktopWindow());
3165 ok(ret, "Failed to set foreground window.\n");
3166 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3167 memset(&devmode, 0, sizeof(devmode));
3168 devmode.dmSize = sizeof(devmode);
3169 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3170 ok(ret, "Failed to get display mode.\n");
3171 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3172 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpected screen size %lux%lu.\n",
3173 devmode.dmPelsWidth, devmode.dmPelsHeight);
3175 expect_messages = exclusive_focus_restore_messages;
3176 ShowWindow(window, SW_RESTORE);
3177 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3179 GetWindowRect(window, &r);
3180 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3181 wine_dbgstr_rect(&r));
3182 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3183 ok(ret, "Failed to get display mode.\n");
3184 ok(devmode.dmPelsWidth == param.ddraw_width
3185 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpected screen size %lux%lu.\n",
3186 devmode.dmPelsWidth, devmode.dmPelsHeight);
3188 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3189 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3190 /* Normally the primary should be restored here. Unfortunately this causes the
3191 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
3192 * testbot. Another Restore call would presumably avoid the crash, but it also moots
3193 * the point of the GetSurfaceDesc call. */
3195 expect_messages = sc_minimize_messages;
3196 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3197 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3198 expect_messages = NULL;
3200 expect_messages = sc_restore_messages;
3201 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
3202 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3203 expect_messages = NULL;
3205 expect_messages = sc_maximize_messages;
3206 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3207 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3208 expect_messages = NULL;
3210 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3211 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3213 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3214 expect_messages = exclusive_messages;
3215 screen_size.cx = 0;
3216 screen_size.cy = 0;
3218 hr = IDirectDrawSurface_IsLost(primary);
3219 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3220 hr = IDirectDraw_RestoreDisplayMode(ddraw);
3221 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#lx.\n", hr);
3222 hr = IDirectDrawSurface_IsLost(primary);
3223 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3225 flaky /* win8 */
3226 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3227 expect_messages = NULL;
3228 flaky /* win8 */
3229 ok(screen_size.cx == registry_mode.dmPelsWidth
3230 && screen_size.cy == registry_mode.dmPelsHeight,
3231 "Expected screen size %lux%lu, got %lux%lu.\n",
3232 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
3234 GetWindowRect(window, &r);
3235 flaky /* win8 */
3236 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3237 wine_dbgstr_rect(&r));
3239 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3240 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3241 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3242 param.ddraw_width, ddsd.dwWidth);
3243 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3244 param.ddraw_height, ddsd.dwHeight);
3245 IDirectDrawSurface_Release(primary);
3247 /* For Wine. */
3248 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3249 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3251 memset(&ddsd, 0, sizeof(ddsd));
3252 ddsd.dwSize = sizeof(ddsd);
3253 ddsd.dwFlags = DDSD_CAPS;
3254 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3256 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3257 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3258 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3259 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3260 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3261 registry_mode.dmPelsWidth, ddsd.dwWidth);
3262 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3263 registry_mode.dmPelsHeight, ddsd.dwHeight);
3265 GetWindowRect(window, &r);
3266 flaky /* win8 */
3267 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3268 wine_dbgstr_rect(&r));
3270 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3271 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3273 GetWindowRect(window, &r);
3274 flaky /* win8 */
3275 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3276 wine_dbgstr_rect(&r));
3278 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3279 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3280 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3281 registry_mode.dmPelsWidth, ddsd.dwWidth);
3282 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3283 registry_mode.dmPelsHeight, ddsd.dwHeight);
3284 IDirectDrawSurface_Release(primary);
3286 memset(&ddsd, 0, sizeof(ddsd));
3287 ddsd.dwSize = sizeof(ddsd);
3288 ddsd.dwFlags = DDSD_CAPS;
3289 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3291 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3292 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3293 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3294 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3295 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3296 registry_mode.dmPelsWidth, ddsd.dwWidth);
3297 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3298 registry_mode.dmPelsHeight, ddsd.dwHeight);
3300 GetWindowRect(window, &r);
3301 flaky /* win8 */
3302 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3303 wine_dbgstr_rect(&r));
3305 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3306 expect_messages = normal_messages;
3307 screen_size.cx = 0;
3308 screen_size.cy = 0;
3310 hr = IDirectDrawSurface_IsLost(primary);
3311 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3312 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3313 devmode.dmPelsWidth = param.user32_width;
3314 devmode.dmPelsHeight = param.user32_height;
3315 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3316 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3317 hr = IDirectDrawSurface_IsLost(primary);
3318 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3320 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3321 expect_messages = NULL;
3322 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3324 GetWindowRect(window, &r);
3325 flaky /* win8 */
3326 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3327 wine_dbgstr_rect(&r));
3329 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3330 expect_messages = normal_messages;
3331 screen_size.cx = 0;
3332 screen_size.cy = 0;
3334 hr = IDirectDrawSurface_Restore(primary);
3335 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
3336 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3337 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
3339 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
3340 IDirectDrawSurface_Release(primary);
3341 IDirectDraw_Release(ddraw);
3342 goto done;
3344 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3345 hr = IDirectDrawSurface_Restore(primary);
3346 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
3347 hr = IDirectDrawSurface_IsLost(primary);
3348 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3350 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3351 expect_messages = NULL;
3352 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3354 GetWindowRect(window, &r);
3355 flaky /* win8 */
3356 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3357 wine_dbgstr_rect(&r));
3359 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3360 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3361 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3362 registry_mode.dmPelsWidth, ddsd.dwWidth);
3363 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3364 registry_mode.dmPelsHeight, ddsd.dwHeight);
3365 IDirectDrawSurface_Release(primary);
3367 memset(&ddsd, 0, sizeof(ddsd));
3368 ddsd.dwSize = sizeof(ddsd);
3369 ddsd.dwFlags = DDSD_CAPS;
3370 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3372 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3373 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3374 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3375 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3376 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3377 param.ddraw_width, ddsd.dwWidth);
3378 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3379 param.ddraw_height, ddsd.dwHeight);
3381 GetWindowRect(window, &r);
3382 flaky /* win8 */
3383 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3384 wine_dbgstr_rect(&r));
3386 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3387 expect_messages = normal_messages;
3388 screen_size.cx = 0;
3389 screen_size.cy = 0;
3391 hr = IDirectDrawSurface_IsLost(primary);
3392 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3393 hr = IDirectDraw_RestoreDisplayMode(ddraw);
3394 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#lx.\n", hr);
3395 hr = IDirectDrawSurface_IsLost(primary);
3396 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3398 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3399 expect_messages = NULL;
3400 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3402 GetWindowRect(window, &r);
3403 flaky /* win8 */
3404 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3405 wine_dbgstr_rect(&r));
3407 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3408 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3409 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3410 param.ddraw_width, ddsd.dwWidth);
3411 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3412 param.ddraw_height, ddsd.dwHeight);
3413 IDirectDrawSurface_Release(primary);
3415 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3416 ok(ret, "Failed to get display mode.\n");
3417 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3418 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3419 "Expected resolution %lux%lu, got %lux%lu.\n",
3420 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3421 devmode.dmPelsWidth, devmode.dmPelsHeight);
3422 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3423 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3425 memset(&ddsd, 0, sizeof(ddsd));
3426 ddsd.dwSize = sizeof(ddsd);
3427 ddsd.dwFlags = DDSD_CAPS;
3428 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3430 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3431 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3432 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3433 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3434 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3435 registry_mode.dmPelsWidth, ddsd.dwWidth);
3436 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3437 registry_mode.dmPelsHeight, ddsd.dwHeight);
3439 GetWindowRect(window, &r);
3440 flaky /* win8 */
3441 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3442 wine_dbgstr_rect(&r));
3444 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
3445 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
3446 * not DDSCL_FULLSCREEN. */
3447 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3448 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3450 GetWindowRect(window, &r);
3451 flaky /* win8 */
3452 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3453 wine_dbgstr_rect(&r));
3455 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3456 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3457 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3458 registry_mode.dmPelsWidth, ddsd.dwWidth);
3459 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3460 registry_mode.dmPelsHeight, ddsd.dwHeight);
3461 IDirectDrawSurface_Release(primary);
3463 memset(&ddsd, 0, sizeof(ddsd));
3464 ddsd.dwSize = sizeof(ddsd);
3465 ddsd.dwFlags = DDSD_CAPS;
3466 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3468 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3469 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3470 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3471 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3472 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3473 registry_mode.dmPelsWidth, ddsd.dwWidth);
3474 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3475 registry_mode.dmPelsHeight, ddsd.dwHeight);
3477 GetWindowRect(window, &r);
3478 flaky /* win8 */
3479 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3480 wine_dbgstr_rect(&r));
3482 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3483 expect_messages = normal_messages;
3484 screen_size.cx = 0;
3485 screen_size.cy = 0;
3487 hr = IDirectDrawSurface_IsLost(primary);
3488 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3489 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3490 devmode.dmPelsWidth = param.user32_width;
3491 devmode.dmPelsHeight = param.user32_height;
3492 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3493 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3494 hr = IDirectDrawSurface_IsLost(primary);
3495 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3497 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3498 expect_messages = NULL;
3499 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3501 GetWindowRect(window, &r);
3502 flaky /* win8 */
3503 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3504 wine_dbgstr_rect(&r));
3506 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3507 expect_messages = normal_messages;
3508 screen_size.cx = 0;
3509 screen_size.cy = 0;
3511 hr = IDirectDrawSurface_Restore(primary);
3512 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
3513 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3514 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3515 hr = IDirectDrawSurface_Restore(primary);
3516 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
3517 hr = IDirectDrawSurface_IsLost(primary);
3518 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3520 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3521 expect_messages = NULL;
3522 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3524 GetWindowRect(window, &r);
3525 flaky /* win8 */
3526 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3527 wine_dbgstr_rect(&r));
3529 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3530 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3531 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3532 registry_mode.dmPelsWidth, ddsd.dwWidth);
3533 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3534 registry_mode.dmPelsHeight, ddsd.dwHeight);
3535 IDirectDrawSurface_Release(primary);
3537 memset(&ddsd, 0, sizeof(ddsd));
3538 ddsd.dwSize = sizeof(ddsd);
3539 ddsd.dwFlags = DDSD_CAPS;
3540 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3542 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3543 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3544 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3545 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3546 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3547 param.ddraw_width, ddsd.dwWidth);
3548 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3549 param.ddraw_height, ddsd.dwHeight);
3551 GetWindowRect(window, &r);
3552 flaky /* win8 */
3553 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3554 wine_dbgstr_rect(&r));
3556 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3557 expect_messages = normal_messages;
3558 screen_size.cx = 0;
3559 screen_size.cy = 0;
3561 hr = IDirectDrawSurface_IsLost(primary);
3562 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3563 hr = IDirectDraw_RestoreDisplayMode(ddraw);
3564 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#lx.\n", hr);
3565 hr = IDirectDrawSurface_IsLost(primary);
3566 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3568 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3569 expect_messages = NULL;
3570 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3572 GetWindowRect(window, &r);
3573 flaky /* win8 */
3574 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3575 wine_dbgstr_rect(&r));
3577 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3578 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3579 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3580 param.ddraw_width, ddsd.dwWidth);
3581 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3582 param.ddraw_height, ddsd.dwHeight);
3583 IDirectDrawSurface_Release(primary);
3585 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3586 ok(ret, "Failed to get display mode.\n");
3587 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3588 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3589 "Expected resolution %lux%lu, got %lux%lu.\n",
3590 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3591 devmode.dmPelsWidth, devmode.dmPelsHeight);
3592 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3593 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3595 memset(&ddsd, 0, sizeof(ddsd));
3596 ddsd.dwSize = sizeof(ddsd);
3597 ddsd.dwFlags = DDSD_CAPS;
3598 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3600 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3601 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3602 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3603 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3604 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3605 registry_mode.dmPelsWidth, ddsd.dwWidth);
3606 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3607 registry_mode.dmPelsHeight, ddsd.dwHeight);
3608 IDirectDrawSurface_Release(primary);
3610 GetWindowRect(window, &r);
3611 flaky /* win8 */
3612 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3613 wine_dbgstr_rect(&r));
3615 /* Unlike ddraw2-7, changing from EXCLUSIVE to NORMAL does not restore the resolution */
3616 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3617 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3618 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3619 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3621 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3622 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3624 memset(&ddsd, 0, sizeof(ddsd));
3625 ddsd.dwSize = sizeof(ddsd);
3626 ddsd.dwFlags = DDSD_CAPS;
3627 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3629 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3630 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3631 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3632 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3633 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3634 param.ddraw_width, ddsd.dwWidth);
3635 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3636 param.ddraw_height, ddsd.dwHeight);
3637 IDirectDrawSurface_Release(primary);
3638 hr = IDirectDraw_RestoreDisplayMode(ddraw);
3639 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#lx.\n", hr);
3641 ref = IDirectDraw_Release(ddraw);
3642 ok(!ref, "Unexpected refcount %lu.\n", ref);
3644 GetWindowRect(window, &r);
3645 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3646 wine_dbgstr_rect(&r));
3648 ret = restore_display_modes(original_modes, display_count);
3649 ok(ret, "Failed to restore display modes.\n");
3651 /* Test that no mode restorations if no mode changes happened */
3652 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3653 devmode.dmPelsWidth = param.user32_width;
3654 devmode.dmPelsHeight = param.user32_height;
3655 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3656 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %ld.\n", change_ret);
3658 ddraw = create_ddraw();
3659 ok(!!ddraw, "Failed to create a ddraw object.\n");
3660 ref = IDirectDraw_Release(ddraw);
3661 ok(!ref, "Unexpected refcount %lu.\n", ref);
3663 memset(&devmode2, 0, sizeof(devmode2));
3664 devmode2.dmSize = sizeof(devmode2);
3665 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3666 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3667 ok(compare_mode_rect(&devmode2, &registry_mode), "Got a different mode.\n");
3668 ret = restore_display_modes(original_modes, display_count);
3669 ok(ret, "Failed to restore display modes.\n");
3671 /* Test that no mode restorations if no mode changes happened with fullscreen ddraw objects */
3672 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3673 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %ld.\n", change_ret);
3675 ddraw = create_ddraw();
3676 ok(!!ddraw, "Failed to create a ddraw object.\n");
3677 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3678 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
3679 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3680 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
3681 ref = IDirectDraw_Release(ddraw);
3682 ok(!ref, "Unexpected refcount %lu.\n", ref);
3684 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3685 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3686 ok(compare_mode_rect(&devmode2, &registry_mode), "Got a different mode.\n");
3687 ret = restore_display_modes(original_modes, display_count);
3688 ok(ret, "Failed to restore display modes.\n");
3690 /* Test that mode restorations use display settings in the registry after ddraw object releases
3691 * if SetDisplayMode() was called */
3692 ddraw = create_ddraw();
3693 ok(!!ddraw, "Failed to create a ddraw object.\n");
3694 hr = set_display_mode(ddraw, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3695 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
3697 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3698 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %ld.\n", change_ret);
3700 ref = IDirectDraw_Release(ddraw);
3701 ok(!ref, "Unexpected refcount %lu.\n", ref);
3703 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3704 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3705 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3706 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
3707 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3708 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3709 ret = restore_display_modes(original_modes, display_count);
3710 ok(ret, "Failed to restore display modes.\n");
3712 /* Test that mode restorations use display settings in the registry after RestoreDisplayMode() */
3713 ddraw = create_ddraw();
3714 ok(!!ddraw, "Failed to create a ddraw object.\n");
3715 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3716 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
3718 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3719 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %ld.\n", change_ret);
3721 hr = IDirectDraw_RestoreDisplayMode(ddraw);
3722 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#lx.\n", hr);
3724 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3725 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3726 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3727 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
3728 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3729 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3731 ref = IDirectDraw_Release(ddraw);
3732 ok(!ref, "Unexpected refcount %lu.\n", ref);
3734 done:
3735 expect_messages = NULL;
3736 DestroyWindow(window);
3737 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3738 ret = restore_display_modes(original_modes, display_count);
3739 ok(ret, "Failed to restore display modes.\n");
3740 free(original_modes);
3743 static void test_coop_level_mode_set_multi(void)
3745 DEVMODEW old_devmode, devmode, devmode2, devmode3, *original_modes = NULL;
3746 unsigned int mode_idx = 0, display_idx, display_count = 0;
3747 WCHAR second_monitor_name[CCHDEVICENAME];
3748 IDirectDraw *ddraw1, *ddraw2;
3749 LONG change_ret;
3750 UINT w, h;
3751 HWND window;
3752 HRESULT hr;
3753 ULONG ref;
3754 BOOL ret;
3756 memset(&devmode, 0, sizeof(devmode));
3757 devmode.dmSize = sizeof(devmode);
3758 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3759 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3760 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3761 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
3762 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3763 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3765 ret = save_display_modes(&original_modes, &display_count);
3766 ok(ret, "Failed to save original display modes.\n");
3768 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3769 0, 0, 100, 100, 0, 0, 0, 0);
3770 ddraw1 = create_ddraw();
3771 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3773 /* With just a single ddraw object, the display mode is restored on
3774 * release. */
3775 hr = set_display_mode(ddraw1, 800, 600);
3776 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
3778 win_skip("Broken SetDisplayMode(), skipping test.\n");
3779 IDirectDraw_Release(ddraw1);
3780 DestroyWindow(window);
3781 return;
3783 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3784 w = GetSystemMetrics(SM_CXSCREEN);
3785 ok(w == 800, "Got unexpected screen width %u.\n", w);
3786 h = GetSystemMetrics(SM_CYSCREEN);
3787 ok(h == 600, "Got unexpected screen height %u.\n", h);
3789 ref = IDirectDraw_Release(ddraw1);
3790 ok(!ref, "Unexpected refcount %lu.\n", ref);
3791 w = GetSystemMetrics(SM_CXSCREEN);
3792 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3793 h = GetSystemMetrics(SM_CYSCREEN);
3794 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3796 /* When there are multiple ddraw objects, the display mode is restored to
3797 * the initial mode, before the first SetDisplayMode() call. */
3798 ddraw1 = create_ddraw();
3799 hr = set_display_mode(ddraw1, 800, 600);
3800 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3801 w = GetSystemMetrics(SM_CXSCREEN);
3802 ok(w == 800, "Got unexpected screen width %u.\n", w);
3803 h = GetSystemMetrics(SM_CYSCREEN);
3804 ok(h == 600, "Got unexpected screen height %u.\n", h);
3806 ddraw2 = create_ddraw();
3807 hr = set_display_mode(ddraw2, 640, 480);
3808 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3809 w = GetSystemMetrics(SM_CXSCREEN);
3810 ok(w == 640, "Got unexpected screen width %u.\n", w);
3811 h = GetSystemMetrics(SM_CYSCREEN);
3812 ok(h == 480, "Got unexpected screen height %u.\n", h);
3814 ref = IDirectDraw_Release(ddraw2);
3815 ok(!ref, "Unexpected refcount %lu.\n", ref);
3816 w = GetSystemMetrics(SM_CXSCREEN);
3817 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3818 h = GetSystemMetrics(SM_CYSCREEN);
3819 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3821 ref = IDirectDraw_Release(ddraw1);
3822 ok(!ref, "Unexpected refcount %lu.\n", ref);
3823 w = GetSystemMetrics(SM_CXSCREEN);
3824 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3825 h = GetSystemMetrics(SM_CYSCREEN);
3826 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3828 /* Regardless of release ordering. */
3829 ddraw1 = create_ddraw();
3830 hr = set_display_mode(ddraw1, 800, 600);
3831 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3832 w = GetSystemMetrics(SM_CXSCREEN);
3833 ok(w == 800, "Got unexpected screen width %u.\n", w);
3834 h = GetSystemMetrics(SM_CYSCREEN);
3835 ok(h == 600, "Got unexpected screen height %u.\n", h);
3837 ddraw2 = create_ddraw();
3838 hr = set_display_mode(ddraw2, 640, 480);
3839 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3840 w = GetSystemMetrics(SM_CXSCREEN);
3841 ok(w == 640, "Got unexpected screen width %u.\n", w);
3842 h = GetSystemMetrics(SM_CYSCREEN);
3843 ok(h == 480, "Got unexpected screen height %u.\n", h);
3845 ref = IDirectDraw_Release(ddraw1);
3846 ok(!ref, "Unexpected refcount %lu.\n", ref);
3847 w = GetSystemMetrics(SM_CXSCREEN);
3848 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3849 h = GetSystemMetrics(SM_CYSCREEN);
3850 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3852 ref = IDirectDraw_Release(ddraw2);
3853 ok(!ref, "Unexpected refcount %lu.\n", ref);
3854 w = GetSystemMetrics(SM_CXSCREEN);
3855 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3856 h = GetSystemMetrics(SM_CYSCREEN);
3857 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3859 /* But only for ddraw objects that called SetDisplayMode(). */
3860 ddraw1 = create_ddraw();
3861 ddraw2 = create_ddraw();
3862 hr = set_display_mode(ddraw2, 640, 480);
3863 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3864 w = GetSystemMetrics(SM_CXSCREEN);
3865 ok(w == 640, "Got unexpected screen width %u.\n", w);
3866 h = GetSystemMetrics(SM_CYSCREEN);
3867 ok(h == 480, "Got unexpected screen height %u.\n", h);
3869 ref = IDirectDraw_Release(ddraw1);
3870 ok(!ref, "Unexpected refcount %lu.\n", ref);
3871 w = GetSystemMetrics(SM_CXSCREEN);
3872 ok(w == 640, "Got unexpected screen width %u.\n", w);
3873 h = GetSystemMetrics(SM_CYSCREEN);
3874 ok(h == 480, "Got unexpected screen height %u.\n", h);
3876 ref = IDirectDraw_Release(ddraw2);
3877 ok(!ref, "Unexpected refcount %lu.\n", ref);
3878 w = GetSystemMetrics(SM_CXSCREEN);
3879 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3880 h = GetSystemMetrics(SM_CYSCREEN);
3881 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3883 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3884 * restoring the display mode. */
3885 ddraw1 = create_ddraw();
3886 hr = set_display_mode(ddraw1, 800, 600);
3887 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3888 w = GetSystemMetrics(SM_CXSCREEN);
3889 ok(w == 800, "Got unexpected screen width %u.\n", w);
3890 h = GetSystemMetrics(SM_CYSCREEN);
3891 ok(h == 600, "Got unexpected screen height %u.\n", h);
3893 ddraw2 = create_ddraw();
3894 hr = set_display_mode(ddraw2, 640, 480);
3895 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3896 w = GetSystemMetrics(SM_CXSCREEN);
3897 ok(w == 640, "Got unexpected screen width %u.\n", w);
3898 h = GetSystemMetrics(SM_CYSCREEN);
3899 ok(h == 480, "Got unexpected screen height %u.\n", h);
3901 hr = IDirectDraw_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3902 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3904 ref = IDirectDraw_Release(ddraw1);
3905 ok(!ref, "Unexpected refcount %lu.\n", ref);
3906 w = GetSystemMetrics(SM_CXSCREEN);
3907 ok(w == 640, "Got unexpected screen width %u.\n", w);
3908 h = GetSystemMetrics(SM_CYSCREEN);
3909 ok(h == 480, "Got unexpected screen height %u.\n", h);
3911 ref = IDirectDraw_Release(ddraw2);
3912 ok(!ref, "Unexpected refcount %lu.\n", ref);
3913 w = GetSystemMetrics(SM_CXSCREEN);
3914 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3915 h = GetSystemMetrics(SM_CYSCREEN);
3916 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3918 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3919 ddraw1 = create_ddraw();
3920 hr = set_display_mode(ddraw1, 800, 600);
3921 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3922 w = GetSystemMetrics(SM_CXSCREEN);
3923 ok(w == 800, "Got unexpected screen width %u.\n", w);
3924 h = GetSystemMetrics(SM_CYSCREEN);
3925 ok(h == 600, "Got unexpected screen height %u.\n", h);
3927 hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3928 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3930 ddraw2 = create_ddraw();
3931 hr = set_display_mode(ddraw2, 640, 480);
3932 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
3934 ref = IDirectDraw_Release(ddraw1);
3935 ok(!ref, "Unexpected refcount %lu.\n", ref);
3936 w = GetSystemMetrics(SM_CXSCREEN);
3937 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3938 h = GetSystemMetrics(SM_CYSCREEN);
3939 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3941 ref = IDirectDraw_Release(ddraw2);
3942 ok(!ref, "Unexpected refcount %lu.\n", ref);
3943 w = GetSystemMetrics(SM_CXSCREEN);
3944 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3945 h = GetSystemMetrics(SM_CYSCREEN);
3946 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3948 if (display_count < 2)
3950 skip("Following tests require two monitors.\n");
3951 goto done;
3954 ret = restore_display_modes(original_modes, display_count);
3955 ok(ret, "Failed to restore display modes.\n");
3957 second_monitor_name[0] = '\0';
3958 for (display_idx = 0; display_idx < display_count; ++display_idx)
3960 if (original_modes[display_idx].dmPosition.x || original_modes[display_idx].dmPosition.y)
3962 lstrcpyW(second_monitor_name, original_modes[display_idx].dmDeviceName);
3963 break;
3966 ok(lstrlenW(second_monitor_name), "Got an empty second monitor name.\n");
3967 memset(&old_devmode, 0, sizeof(old_devmode));
3968 old_devmode.dmSize = sizeof(old_devmode);
3969 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
3970 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3972 devmode = old_devmode;
3973 while (EnumDisplaySettingsW(second_monitor_name, mode_idx++, &devmode))
3975 if (devmode.dmPelsWidth != old_devmode.dmPelsWidth
3976 || devmode.dmPelsHeight != old_devmode.dmPelsHeight)
3977 break;
3979 ok(devmode.dmPelsWidth != old_devmode.dmPelsWidth
3980 || devmode.dmPelsHeight != old_devmode.dmPelsHeight,
3981 "Failed to find a different mode for the second monitor.\n");
3983 /* Test that no mode restorations for non-primary monitors if SetDisplayMode() was not called */
3984 ddraw1 = create_ddraw();
3985 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3986 hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3987 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
3989 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
3990 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
3992 memset(&devmode2, 0, sizeof(devmode2));
3993 devmode2.dmSize = sizeof(devmode2);
3994 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
3995 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3996 if (compare_mode_rect(&devmode2, &old_devmode))
3998 skip("Failed to change display settings of the second monitor.\n");
3999 ref = IDirectDraw_Release(ddraw1);
4000 ok(!ref, "Unexpected refcount %lu.\n", ref);
4001 goto done;
4004 hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_NORMAL);
4005 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
4006 ref = IDirectDraw_Release(ddraw1);
4007 ok(!ref, "Unexpected refcount %lu.\n", ref);
4009 memset(&devmode3, 0, sizeof(devmode3));
4010 devmode3.dmSize = sizeof(devmode3);
4011 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode3);
4012 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4013 ok(compare_mode_rect(&devmode3, &devmode2), "Got a different mode.\n");
4014 ret = restore_display_modes(original_modes, display_count);
4015 ok(ret, "Failed to restore display modes.\n");
4017 /* Test that mode restorations happen for non-primary monitors on ddraw releases if
4018 * SetDisplayMode() was called */
4019 ddraw1 = create_ddraw();
4020 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4021 hr = set_display_mode(ddraw1, 800, 600);
4022 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4024 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4025 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4027 ref = IDirectDraw_Release(ddraw1);
4028 ok(!ref, "Unexpected refcount %lu.\n", ref);
4030 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4031 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4032 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4033 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4034 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4035 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4036 ret = restore_display_modes(original_modes, display_count);
4037 ok(ret, "Failed to restore display modes.\n");
4039 /* Test that mode restorations happen for non-primary monitors as well */
4040 ddraw1 = create_ddraw();
4041 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4042 hr = set_display_mode(ddraw1, 800, 600);
4043 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4045 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4046 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4048 hr = IDirectDraw_RestoreDisplayMode(ddraw1);
4049 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#lx.\n", hr);
4051 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4052 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4053 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4054 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4055 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4056 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4058 ref = IDirectDraw_Release(ddraw1);
4059 ok(!ref, "Unexpected refcount %lu.\n", ref);
4060 ret = restore_display_modes(original_modes, display_count);
4061 ok(ret, "Failed to restore display modes.\n");
4063 /* Test that mode restorations for non-primary monitors use display settings in the registry */
4064 ddraw1 = create_ddraw();
4065 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4066 hr = set_display_mode(ddraw1, 800, 600);
4067 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4069 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
4070 CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
4071 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4073 ref = IDirectDraw_Release(ddraw1);
4074 ok(!ref, "Unexpected refcount %lu.\n", ref);
4076 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4077 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4078 ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
4079 "Expected resolution %lux%lu, got %lux%lu.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
4080 devmode2.dmPelsWidth, devmode2.dmPelsHeight);
4081 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4082 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4083 ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
4084 "Expected resolution %lux%lu, got %lux%lu.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
4085 devmode2.dmPelsWidth, devmode2.dmPelsHeight);
4086 ret = restore_display_modes(original_modes, display_count);
4087 ok(ret, "Failed to restore display modes.\n");
4089 /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
4090 * objects and one of them restores display mode */
4091 ddraw1 = create_ddraw();
4092 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4093 ddraw2 = create_ddraw();
4094 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4095 hr = set_display_mode(ddraw1, 800, 600);
4096 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4097 hr = set_display_mode(ddraw2, 640, 480);
4098 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4100 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4101 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4103 hr = IDirectDraw_RestoreDisplayMode(ddraw2);
4104 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#lx.\n", hr);
4106 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4107 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4108 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4109 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4110 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4111 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4113 ref = IDirectDraw_Release(ddraw2);
4114 ok(!ref, "Unexpected refcount %lu.\n", ref);
4115 ref = IDirectDraw_Release(ddraw1);
4116 ok(!ref, "Unexpected refcount %lu.\n", ref);
4117 ret = restore_display_modes(original_modes, display_count);
4118 ok(ret, "Failed to restore display modes.\n");
4120 /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
4121 * objects and one of them got released */
4122 ddraw1 = create_ddraw();
4123 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4124 ddraw2 = create_ddraw();
4125 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4126 hr = set_display_mode(ddraw1, 800, 600);
4127 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4128 hr = set_display_mode(ddraw2, 640, 480);
4129 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4131 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4132 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4134 ref = IDirectDraw_Release(ddraw2);
4135 ok(!ref, "Unexpected refcount %lu.\n", ref);
4137 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4138 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4139 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4140 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4141 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4142 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4144 ref = IDirectDraw_Release(ddraw1);
4145 ok(!ref, "Unexpected refcount %lu.\n", ref);
4147 done:
4148 DestroyWindow(window);
4149 ret = restore_display_modes(original_modes, display_count);
4150 ok(ret, "Failed to restore display modes.\n");
4151 free(original_modes);
4154 static void test_initialize(void)
4156 IDirectDraw *ddraw;
4157 IDirect3D *d3d;
4158 HRESULT hr;
4160 ddraw = create_ddraw();
4161 ok(!!ddraw, "Failed to create a ddraw object.\n");
4163 hr = IDirectDraw_Initialize(ddraw, NULL);
4164 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#lx.\n", hr);
4165 IDirectDraw_Release(ddraw);
4167 CoInitialize(NULL);
4168 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw);
4169 ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#lx.\n", hr);
4170 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
4171 if (SUCCEEDED(hr))
4173 /* IDirect3D_Initialize() just returns DDERR_ALREADYINITIALIZED. */
4174 hr = IDirect3D_Initialize(d3d, NULL);
4175 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#lx, expected DDERR_ALREADYINITIALIZED.\n", hr);
4176 IDirect3D_Release(d3d);
4178 else
4179 skip("D3D interface is not available, skipping test.\n");
4180 hr = IDirectDraw_Initialize(ddraw, NULL);
4181 ok(hr == DD_OK, "Initialize returned hr %#lx, expected DD_OK.\n", hr);
4182 hr = IDirectDraw_Initialize(ddraw, NULL);
4183 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#lx, expected DDERR_ALREADYINITIALIZED.\n", hr);
4184 IDirectDraw_Release(ddraw);
4185 CoUninitialize();
4187 if (0) /* This crashes on the W2KPROSP4 testbot. */
4189 CoInitialize(NULL);
4190 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d);
4191 ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#lx, expected E_NOINTERFACE.\n", hr);
4192 CoUninitialize();
4196 static void test_coop_level_surf_create(void)
4198 IDirectDrawSurface *surface;
4199 IDirectDraw *ddraw;
4200 DDSURFACEDESC ddsd;
4201 HRESULT hr;
4203 ddraw = create_ddraw();
4204 ok(!!ddraw, "Failed to create a ddraw object.\n");
4206 memset(&ddsd, 0, sizeof(ddsd));
4207 ddsd.dwSize = sizeof(ddsd);
4208 ddsd.dwFlags = DDSD_CAPS;
4209 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4210 surface = (void *)0xdeadbeef;
4211 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4212 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#lx.\n", hr);
4213 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4215 surface = (void *)0xdeadbeef;
4216 hr = IDirectDraw_CreateSurface(ddraw, NULL, &surface, NULL);
4217 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#lx.\n", hr);
4218 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4220 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4221 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4223 surface = (void *)0xdeadbeef;
4224 hr = IDirectDraw_CreateSurface(ddraw, NULL, &surface, NULL);
4225 ok(hr == DDERR_INVALIDPARAMS, "Unexpected hr %#lx.\n", hr);
4226 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4228 IDirectDraw_Release(ddraw);
4231 static void test_coop_level_multi_window(void)
4233 HWND window1, window2;
4234 IDirectDraw *ddraw;
4235 HRESULT hr;
4237 window1 = create_window();
4238 window2 = create_window();
4239 ddraw = create_ddraw();
4240 ok(!!ddraw, "Failed to create a ddraw object.\n");
4242 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
4243 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4244 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
4245 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4246 ok(IsWindow(window1), "Window 1 was destroyed.\n");
4247 ok(IsWindow(window2), "Window 2 was destroyed.\n");
4249 IDirectDraw_Release(ddraw);
4250 DestroyWindow(window2);
4251 DestroyWindow(window1);
4254 static void test_clear_rect_count(void)
4256 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4257 IDirect3DMaterial *white, *red, *green, *blue;
4258 IDirect3DViewport *viewport;
4259 IDirect3DDevice *device;
4260 IDirectDrawSurface *rt;
4261 unsigned int color;
4262 IDirectDraw *ddraw;
4263 HWND window;
4264 HRESULT hr;
4266 window = create_window();
4267 ddraw = create_ddraw();
4268 ok(!!ddraw, "Failed to create a ddraw object.\n");
4269 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4271 skip("Failed to create a 3D device, skipping test.\n");
4272 IDirectDraw_Release(ddraw);
4273 DestroyWindow(window);
4274 return;
4277 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
4278 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
4280 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
4281 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
4282 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
4283 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
4284 viewport = create_viewport(device, 0, 0, 640, 480);
4286 viewport_set_background(device, viewport, white);
4287 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
4288 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
4289 viewport_set_background(device, viewport, red);
4290 hr = IDirect3DViewport_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
4291 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
4292 viewport_set_background(device, viewport, green);
4293 hr = IDirect3DViewport_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
4294 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
4295 viewport_set_background(device, viewport, blue);
4296 hr = IDirect3DViewport_Clear(viewport, 1, NULL, D3DCLEAR_TARGET);
4297 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
4299 color = get_surface_color(rt, 320, 240);
4300 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x000000ff, 1)),
4301 "Got unexpected color 0x%08x.\n", color);
4303 IDirectDrawSurface_Release(rt);
4304 destroy_viewport(device, viewport);
4305 destroy_material(white);
4306 destroy_material(red);
4307 destroy_material(green);
4308 destroy_material(blue);
4309 IDirect3DDevice_Release(device);
4310 IDirectDraw_Release(ddraw);
4311 DestroyWindow(window);
4314 static struct
4316 BOOL received;
4317 IDirectDraw *ddraw;
4318 HWND window;
4319 DWORD coop_level;
4320 } activateapp_testdata;
4322 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
4324 if (message == WM_ACTIVATEAPP)
4326 if (activateapp_testdata.ddraw)
4328 HRESULT hr;
4329 activateapp_testdata.received = FALSE;
4330 hr = IDirectDraw_SetCooperativeLevel(activateapp_testdata.ddraw,
4331 activateapp_testdata.window, activateapp_testdata.coop_level);
4332 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#lx.\n", hr);
4333 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
4335 activateapp_testdata.received = TRUE;
4338 return DefWindowProcA(hwnd, message, wparam, lparam);
4341 static void test_coop_level_activateapp(void)
4343 IDirectDraw *ddraw;
4344 HRESULT hr;
4345 HWND window;
4346 WNDCLASSA wc = {0};
4347 DDSURFACEDESC ddsd;
4348 IDirectDrawSurface *surface;
4350 ddraw = create_ddraw();
4351 ok(!!ddraw, "Failed to create a ddraw object.\n");
4353 wc.lpfnWndProc = activateapp_test_proc;
4354 wc.lpszClassName = "ddraw_test_wndproc_wc";
4355 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4357 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
4358 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
4360 /* Exclusive with window already active. */
4361 SetForegroundWindow(window);
4362 activateapp_testdata.received = FALSE;
4363 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4364 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4365 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
4366 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4367 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4369 /* Exclusive with window not active. */
4370 SetForegroundWindow(GetDesktopWindow());
4371 activateapp_testdata.received = FALSE;
4372 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4373 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4374 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4375 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4376 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4378 /* Normal with window not active, then exclusive with the same window. */
4379 SetForegroundWindow(GetDesktopWindow());
4380 activateapp_testdata.received = FALSE;
4381 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4382 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4383 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
4384 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4385 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4386 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4387 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4388 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4390 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
4391 SetForegroundWindow(GetDesktopWindow());
4392 activateapp_testdata.received = FALSE;
4393 activateapp_testdata.ddraw = ddraw;
4394 activateapp_testdata.window = window;
4395 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
4396 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4397 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4398 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4399 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4400 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4402 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
4403 * succeeding. Another switch to exclusive and back to normal is needed to release the
4404 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
4405 * WM_ACTIVATEAPP messages. */
4406 activateapp_testdata.ddraw = NULL;
4407 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4408 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4409 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4410 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4412 /* Setting DDSCL_NORMAL with recursive invocation. */
4413 SetForegroundWindow(GetDesktopWindow());
4414 activateapp_testdata.received = FALSE;
4415 activateapp_testdata.ddraw = ddraw;
4416 activateapp_testdata.window = window;
4417 activateapp_testdata.coop_level = DDSCL_NORMAL;
4418 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4419 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4420 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4422 /* DDraw is in exclusive mode now. */
4423 memset(&ddsd, 0, sizeof(ddsd));
4424 ddsd.dwSize = sizeof(ddsd);
4425 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4426 ddsd.dwBackBufferCount = 1;
4427 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4428 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4429 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
4430 IDirectDrawSurface_Release(surface);
4432 /* Recover again, just to be sure. */
4433 activateapp_testdata.ddraw = NULL;
4434 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4435 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4436 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4437 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4439 DestroyWindow(window);
4440 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
4441 IDirectDraw_Release(ddraw);
4444 struct format_support_check
4446 const DDPIXELFORMAT *format;
4447 BOOL supported;
4450 static HRESULT WINAPI test_unsupported_formats_cb(DDSURFACEDESC *desc, void *ctx)
4452 struct format_support_check *format = ctx;
4454 if (!memcmp(format->format, &desc->ddpfPixelFormat, sizeof(*format->format)))
4456 format->supported = TRUE;
4457 return DDENUMRET_CANCEL;
4460 return DDENUMRET_OK;
4463 static void test_unsupported_formats(void)
4465 HRESULT hr;
4466 BOOL expect_success;
4467 HWND window;
4468 IDirectDraw *ddraw;
4469 IDirect3DDevice *device;
4470 IDirectDrawSurface *surface;
4471 DDSURFACEDESC ddsd;
4472 unsigned int i, j;
4473 DWORD expected_caps;
4474 static const struct
4476 const char *name;
4477 DDPIXELFORMAT fmt;
4479 formats[] =
4482 "D3DFMT_A8R8G8B8",
4484 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
4485 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
4489 "D3DFMT_P8",
4491 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
4492 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
4496 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
4498 window = create_window();
4499 ddraw = create_ddraw();
4500 ok(!!ddraw, "Failed to create a ddraw object.\n");
4501 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4503 skip("Failed to create a 3D device, skipping test.\n");
4504 IDirectDraw_Release(ddraw);
4505 DestroyWindow(window);
4506 return;
4509 for (i = 0; i < ARRAY_SIZE(formats); i++)
4511 struct format_support_check check = {&formats[i].fmt, FALSE};
4512 hr = IDirect3DDevice_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
4513 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
4515 for (j = 0; j < ARRAY_SIZE(caps); j++)
4517 memset(&ddsd, 0, sizeof(ddsd));
4518 ddsd.dwSize = sizeof(ddsd);
4519 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4520 ddsd.ddpfPixelFormat = formats[i].fmt;
4521 ddsd.dwWidth = 4;
4522 ddsd.dwHeight = 4;
4523 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
4525 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
4526 expect_success = FALSE;
4527 else
4528 expect_success = TRUE;
4530 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4531 ok(SUCCEEDED(hr) == expect_success,
4532 "Got unexpected hr %#lx for format %s, caps %#lx, expected %s.\n",
4533 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
4534 if (FAILED(hr))
4535 continue;
4537 memset(&ddsd, 0, sizeof(ddsd));
4538 ddsd.dwSize = sizeof(ddsd);
4539 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
4540 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
4542 if (caps[j] & DDSCAPS_VIDEOMEMORY)
4543 expected_caps = DDSCAPS_VIDEOMEMORY;
4544 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
4545 expected_caps = DDSCAPS_SYSTEMMEMORY;
4546 else if (check.supported)
4547 expected_caps = DDSCAPS_VIDEOMEMORY;
4548 else
4549 expected_caps = DDSCAPS_SYSTEMMEMORY;
4551 ok(ddsd.ddsCaps.dwCaps & expected_caps,
4552 "Expected caps %#lx, format %s, input caps %#lx.\n",
4553 expected_caps, formats[i].name, caps[j]);
4555 IDirectDrawSurface_Release(surface);
4559 IDirect3DDevice_Release(device);
4560 IDirectDraw_Release(ddraw);
4561 DestroyWindow(window);
4564 static void test_rt_caps(const GUID *device_guid)
4566 DWORD fourcc_codes[64], fourcc_code_count;
4567 PALETTEENTRY palette_entries[256];
4568 IDirectDrawPalette *palette;
4569 IDirect3DDevice *device;
4570 BOOL software_device;
4571 IDirectDraw *ddraw;
4572 DWORD z_depth = 0;
4573 DDCAPS hal_caps;
4574 unsigned int i;
4575 ULONG refcount;
4576 HWND window;
4577 HRESULT hr;
4579 static const DDPIXELFORMAT p8_fmt =
4581 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
4582 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
4584 static const DDPIXELFORMAT fourcc_fmt =
4586 .dwSize = sizeof(DDPIXELFORMAT),
4587 .dwFlags = DDPF_FOURCC,
4588 .dwFourCC = MAKEFOURCC('Y','U','Y','2'),
4591 static const struct
4593 const DDPIXELFORMAT *pf;
4594 DWORD caps_in;
4595 HRESULT create_device_hr;
4596 BOOL create_may_fail;
4598 test_data[] =
4601 NULL,
4602 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
4603 D3D_OK,
4604 FALSE,
4607 NULL,
4608 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4609 D3D_OK,
4610 FALSE,
4613 NULL,
4614 DDSCAPS_OFFSCREENPLAIN,
4615 DDERR_INVALIDCAPS,
4616 FALSE,
4619 NULL,
4620 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4621 D3DERR_SURFACENOTINVIDMEM,
4622 FALSE,
4625 NULL,
4626 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4627 DDERR_INVALIDCAPS,
4628 FALSE,
4631 NULL,
4632 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
4633 D3D_OK,
4634 FALSE,
4637 NULL,
4638 DDSCAPS_3DDEVICE,
4639 D3D_OK,
4640 FALSE,
4643 NULL,
4645 DDERR_INVALIDCAPS,
4646 FALSE,
4649 NULL,
4650 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4651 D3DERR_SURFACENOTINVIDMEM,
4652 FALSE,
4655 NULL,
4656 DDSCAPS_SYSTEMMEMORY,
4657 DDERR_INVALIDCAPS,
4658 FALSE,
4661 &p8_fmt,
4663 DDERR_INVALIDCAPS,
4664 FALSE,
4667 &p8_fmt,
4668 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4669 DDERR_NOPALETTEATTACHED,
4670 FALSE,
4673 &p8_fmt,
4674 DDSCAPS_OFFSCREENPLAIN,
4675 DDERR_INVALIDCAPS,
4676 FALSE,
4679 &p8_fmt,
4680 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4681 DDERR_NOPALETTEATTACHED,
4682 FALSE,
4685 &p8_fmt,
4686 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4687 DDERR_INVALIDCAPS,
4688 FALSE,
4691 NULL,
4692 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
4693 DDERR_INVALIDCAPS,
4694 TRUE /* AMD Evergreen */,
4697 NULL,
4698 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4699 DDERR_INVALIDCAPS,
4700 FALSE,
4703 NULL,
4704 DDSCAPS_ZBUFFER,
4705 DDERR_INVALIDCAPS,
4706 FALSE,
4709 NULL,
4710 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4711 DDERR_INVALIDCAPS,
4712 TRUE /* Nvidia Kepler */,
4715 NULL,
4716 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
4717 DDERR_INVALIDCAPS,
4718 TRUE /* Nvidia Kepler */,
4721 &fourcc_fmt,
4722 DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_OFFSCREENPLAIN,
4723 DDERR_INVALIDCAPS,
4724 FALSE,
4728 software_device = is_software_device_type(device_guid);
4730 window = create_window();
4731 ddraw = create_ddraw();
4732 ok(!!ddraw, "Failed to create a ddraw object.\n");
4733 if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid)))
4735 skip("Failed to create a 3D device, skipping test.\n");
4736 IDirectDraw_Release(ddraw);
4737 DestroyWindow(window);
4738 return;
4740 z_depth = get_device_z_depth(device);
4741 ok(!!z_depth, "Failed to get device z depth.\n");
4742 IDirect3DDevice_Release(device);
4744 memset(palette_entries, 0, sizeof(palette_entries));
4745 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
4746 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
4748 memset(&hal_caps, 0, sizeof(hal_caps));
4749 hal_caps.dwSize = sizeof(hal_caps);
4750 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
4751 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
4753 fourcc_code_count = ARRAY_SIZE(fourcc_codes);
4754 hr = IDirectDraw4_GetFourCCCodes(ddraw, &fourcc_code_count, fourcc_codes);
4755 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
4757 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
4759 DWORD caps_in, expected_caps;
4760 IDirectDrawSurface *surface;
4761 DDSURFACEDESC surface_desc;
4762 IDirect3DDevice *device;
4763 HRESULT expected_hr;
4765 caps_in = test_data[i].caps_in;
4767 memset(&surface_desc, 0, sizeof(surface_desc));
4768 surface_desc.dwSize = sizeof(surface_desc);
4769 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4770 surface_desc.ddsCaps.dwCaps = caps_in;
4771 if (test_data[i].pf)
4773 if (test_data[i].pf->dwFlags & DDPF_FOURCC)
4775 unsigned int j;
4777 for (j = 0; j < fourcc_code_count; ++j)
4779 if (test_data[i].pf->dwFourCC == fourcc_codes[j])
4780 break;
4782 if (j == fourcc_code_count)
4784 skip("Fourcc format %#lx is not supported, skipping test.\n", test_data[i].pf->dwFourCC);
4785 continue;
4788 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
4789 surface_desc.ddpfPixelFormat = *test_data[i].pf;
4791 if (caps_in & DDSCAPS_ZBUFFER)
4793 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
4794 surface_desc.dwZBufferBitDepth = z_depth;
4796 if (caps_in & DDSCAPS_FLIP)
4798 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
4799 surface_desc.dwBackBufferCount = 1;
4801 surface_desc.dwWidth = 640;
4802 surface_desc.dwHeight = 480;
4803 if ((caps_in & DDSCAPS_VIDEOMEMORY) && !(hal_caps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
4804 expected_hr = DDERR_NODIRECTDRAWHW;
4805 else
4806 expected_hr = DD_OK;
4807 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4808 ok(hr == expected_hr || broken(test_data[i].create_may_fail
4809 || (software_device && test_data[i].pf == &p8_fmt && hr == DDERR_INVALIDPIXELFORMAT)),
4810 "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
4811 if (FAILED(hr))
4812 continue;
4814 memset(&surface_desc, 0, sizeof(surface_desc));
4815 surface_desc.dwSize = sizeof(surface_desc);
4816 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4817 ok(hr == DD_OK, "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
4819 if ((caps_in & DDSCAPS_SYSTEMMEMORY) || !(hal_caps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
4820 expected_caps = caps_in | DDSCAPS_SYSTEMMEMORY;
4821 else
4822 expected_caps = caps_in | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
4824 if (caps_in & DDSCAPS_FLIP)
4825 expected_caps |= DDSCAPS_FRONTBUFFER;
4827 ok(surface_desc.ddsCaps.dwCaps == expected_caps || (test_data[i].pf == &p8_fmt
4828 && surface_desc.ddsCaps.dwCaps == (caps_in | DDSCAPS_SYSTEMMEMORY))
4829 || (software_device && caps_in & DDSCAPS_ZBUFFER
4830 && surface_desc.ddsCaps.dwCaps == (caps_in | DDSCAPS_SYSTEMMEMORY)),
4831 "Got unexpected caps %#lx, expected %#lx, test %u, software_device %u.\n",
4832 surface_desc.ddsCaps.dwCaps, expected_caps, i, software_device);
4834 hr = IDirectDrawSurface_QueryInterface(surface, device_guid, (void **)&device);
4835 ok((!software_device && hr == test_data[i].create_device_hr)
4836 || (software_device && (hr == (test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM
4837 ? DD_OK : test_data[i].create_device_hr))),
4838 "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
4839 if (hr == DDERR_NOPALETTEATTACHED)
4841 hr = IDirectDrawSurface_SetPalette(surface, palette);
4842 ok(hr == DD_OK, "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
4843 hr = IDirectDrawSurface_QueryInterface(surface, device_guid, (void **)&device);
4844 if (software_device)
4845 todo_wine
4846 ok(hr == DD_OK, "Got unexpected hr %#lx, test %u, software_device %u.\n",
4847 hr, i, software_device);
4848 else if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
4849 ok(hr == DDERR_INVALIDPIXELFORMAT, "Got unexpected hr %#lx, test %u, software_device %u.\n",
4850 hr, i, software_device);
4851 else
4852 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Got unexpected hr %#lx, test %u, software_device %u.\n",
4853 hr, i, software_device);
4855 if (SUCCEEDED(hr))
4857 refcount = IDirect3DDevice_Release(device);
4858 ok(refcount == 1, "Test %u: Got unexpected refcount %lu.\n", i, refcount);
4861 refcount = IDirectDrawSurface_Release(surface);
4862 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
4865 IDirectDrawPalette_Release(palette);
4866 refcount = IDirectDraw_Release(ddraw);
4867 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
4868 DestroyWindow(window);
4871 static void test_primary_caps(void)
4873 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
4874 IDirectDrawSurface *surface;
4875 DDSURFACEDESC surface_desc;
4876 IDirectDraw *ddraw;
4877 unsigned int i;
4878 ULONG refcount;
4879 HWND window;
4880 HRESULT hr;
4882 static const struct
4884 DWORD coop_level;
4885 DWORD caps_in;
4886 DWORD back_buffer_count;
4887 HRESULT hr;
4888 DWORD caps_out;
4890 test_data[] =
4893 DDSCL_NORMAL,
4894 DDSCAPS_PRIMARYSURFACE,
4895 ~0u,
4896 DD_OK,
4897 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
4900 DDSCL_NORMAL,
4901 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
4902 ~0u,
4903 DDERR_INVALIDCAPS,
4904 ~0u,
4907 DDSCL_NORMAL,
4908 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
4909 ~0u,
4910 DD_OK,
4911 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
4914 DDSCL_NORMAL,
4915 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
4916 ~0u,
4917 DDERR_INVALIDCAPS,
4918 ~0u,
4921 DDSCL_NORMAL,
4922 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
4923 ~0u,
4924 DDERR_INVALIDCAPS,
4925 ~0u,
4928 DDSCL_NORMAL,
4929 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
4930 ~0u,
4931 DDERR_INVALIDCAPS,
4932 ~0u,
4935 DDSCL_NORMAL,
4936 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4937 ~0u,
4938 DDERR_INVALIDCAPS,
4939 ~0u,
4942 DDSCL_NORMAL,
4943 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4945 DDERR_INVALIDCAPS,
4946 ~0u,
4949 DDSCL_NORMAL,
4950 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4952 DDERR_NOEXCLUSIVEMODE,
4953 ~0u,
4956 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4957 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4959 DDERR_INVALIDCAPS,
4960 ~0u,
4963 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4964 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4966 DD_OK,
4967 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
4970 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4971 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
4973 DDERR_INVALIDCAPS,
4974 ~0u,
4977 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4978 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
4980 DDERR_INVALIDCAPS,
4981 ~0u,
4985 window = create_window();
4986 ddraw = create_ddraw();
4987 ok(!!ddraw, "Failed to create a ddraw object.\n");
4989 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
4991 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
4992 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4994 memset(&surface_desc, 0, sizeof(surface_desc));
4995 surface_desc.dwSize = sizeof(surface_desc);
4996 surface_desc.dwFlags = DDSD_CAPS;
4997 if (test_data[i].back_buffer_count != ~0u)
4998 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
4999 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5000 surface_desc.dwBackBufferCount = test_data[i].back_buffer_count;
5001 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5002 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n", i, hr, test_data[i].hr);
5003 if (FAILED(hr))
5004 continue;
5006 memset(&surface_desc, 0, sizeof(surface_desc));
5007 surface_desc.dwSize = sizeof(surface_desc);
5008 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
5009 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#lx.\n", i, hr);
5010 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
5011 "Test %u: Got unexpected caps %#lx, expected %#lx.\n",
5012 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5014 IDirectDrawSurface_Release(surface);
5017 refcount = IDirectDraw_Release(ddraw);
5018 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
5019 DestroyWindow(window);
5022 static void test_surface_lock(void)
5024 IDirectDraw *ddraw;
5025 IDirectDrawSurface *surface;
5026 IDirect3DDevice *device;
5027 HRESULT hr;
5028 HWND window;
5029 unsigned int i;
5030 DDSURFACEDESC ddsd;
5031 ULONG refcount;
5032 DWORD z_depth = 0;
5033 static const struct
5035 DWORD caps;
5036 const char *name;
5038 tests[] =
5041 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
5042 "videomemory offscreenplain"
5045 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5046 "systemmemory offscreenplain"
5049 DDSCAPS_PRIMARYSURFACE,
5050 "primary"
5053 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5054 "videomemory texture"
5057 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
5058 "systemmemory texture"
5061 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5062 "render target"
5065 DDSCAPS_ZBUFFER,
5066 "Z buffer"
5070 window = create_window();
5071 ddraw = create_ddraw();
5072 ok(!!ddraw, "Failed to create a ddraw object.\n");
5073 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
5075 skip("Failed to create a 3D device, skipping test.\n");
5076 IDirectDraw_Release(ddraw);
5077 DestroyWindow(window);
5078 return;
5080 z_depth = get_device_z_depth(device);
5081 ok(!!z_depth, "Failed to get device z depth.\n");
5082 IDirect3DDevice_Release(device);
5084 for (i = 0; i < ARRAY_SIZE(tests); i++)
5086 memset(&ddsd, 0, sizeof(ddsd));
5087 ddsd.dwSize = sizeof(ddsd);
5088 ddsd.dwFlags = DDSD_CAPS;
5089 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
5091 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5092 ddsd.dwWidth = 64;
5093 ddsd.dwHeight = 64;
5095 if (tests[i].caps & DDSCAPS_ZBUFFER)
5097 ddsd.dwFlags |= DDSD_ZBUFFERBITDEPTH;
5098 ddsd.dwZBufferBitDepth = z_depth;
5100 ddsd.ddsCaps.dwCaps = tests[i].caps;
5102 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
5103 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#lx.\n", tests[i].name, hr);
5105 memset(&ddsd, 0, sizeof(ddsd));
5106 ddsd.dwSize = sizeof(ddsd);
5107 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5108 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#lx.\n", tests[i].name, hr);
5109 if (SUCCEEDED(hr))
5111 hr = IDirectDrawSurface_Unlock(surface, NULL);
5112 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#lx.\n", tests[i].name, hr);
5115 memset(&ddsd, 0, sizeof(ddsd));
5116 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5117 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx, type %s.\n", hr, tests[i].name);
5119 IDirectDrawSurface_Release(surface);
5122 refcount = IDirectDraw_Release(ddraw);
5123 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
5124 DestroyWindow(window);
5127 static void test_surface_discard(void)
5129 IDirectDraw *ddraw;
5130 IDirect3DDevice *device;
5131 HRESULT hr;
5132 HWND window;
5133 DDSURFACEDESC ddsd;
5134 IDirectDrawSurface *surface, *target;
5135 void *addr;
5136 static const struct
5138 DWORD caps;
5139 BOOL discard;
5141 tests[] =
5143 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, TRUE},
5144 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, FALSE},
5145 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, TRUE},
5146 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, FALSE},
5148 unsigned int i;
5150 window = create_window();
5152 for (i = 0; i < ARRAY_SIZE(tests); i++)
5154 BOOL discarded;
5156 /* Sigh. Anything other than the first run of the loop randomly fails with
5157 * DDERR_SURFACELOST on my Radeon Pro 560 on Win10 19.09. Most of the time
5158 * the blit fails, but with sleeps added between surface creation and lock
5159 * the lock can fail too. Interestingly ddraw claims the render target has
5160 * been lost, not the test surface.
5162 * Recreating ddraw every iteration seems to fix this. */
5163 ddraw = create_ddraw();
5164 ok(!!ddraw, "Failed to create a ddraw object.\n");
5165 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
5167 skip("Failed to create a 3D device, skipping test.\n");
5168 IDirectDraw_Release(ddraw);
5169 DestroyWindow(window);
5170 return;
5173 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void**)&target);
5174 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
5176 memset(&ddsd, 0, sizeof(ddsd));
5177 ddsd.dwSize = sizeof(ddsd);
5178 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5179 ddsd.ddsCaps.dwCaps = tests[i].caps;
5180 ddsd.dwWidth = 64;
5181 ddsd.dwHeight = 64;
5182 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
5183 if (FAILED(hr))
5185 skip("Failed to create surface, skipping.\n");
5186 continue;
5189 memset(&ddsd, 0, sizeof(ddsd));
5190 ddsd.dwSize = sizeof(ddsd);
5191 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5192 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
5193 addr = ddsd.lpSurface;
5194 hr = IDirectDrawSurface_Unlock(surface, NULL);
5195 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
5197 memset(&ddsd, 0, sizeof(ddsd));
5198 ddsd.dwSize = sizeof(ddsd);
5199 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
5200 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
5201 discarded = ddsd.lpSurface != addr;
5202 hr = IDirectDrawSurface_Unlock(surface, NULL);
5203 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
5205 hr = IDirectDrawSurface_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
5206 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
5208 memset(&ddsd, 0, sizeof(ddsd));
5209 ddsd.dwSize = sizeof(ddsd);
5210 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
5211 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
5212 discarded |= ddsd.lpSurface != addr;
5213 hr = IDirectDrawSurface_Unlock(surface, NULL);
5214 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
5216 IDirectDrawSurface_Release(surface);
5218 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
5219 * AMD r500, evergreen). Windows XP, at least on AMD r200, never changes the pointer. */
5220 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
5222 IDirectDrawSurface_Release(target);
5223 IDirect3DDevice_Release(device);
5224 IDirectDraw_Release(ddraw);
5227 DestroyWindow(window);
5230 static void test_flip(void)
5232 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5233 IDirectDrawSurface *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
5234 DDSCAPS caps = {DDSCAPS_FLIP};
5235 DDSURFACEDESC surface_desc;
5236 unsigned int color, i;
5237 BOOL sysmem_primary;
5238 IDirectDraw *ddraw;
5239 DWORD expected_caps;
5240 ULONG refcount;
5241 HWND window;
5242 HRESULT hr;
5244 static const struct
5246 const char *name;
5247 DWORD caps;
5249 test_data[] =
5251 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
5252 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
5253 {"TEXTURE", DDSCAPS_TEXTURE},
5256 window = create_window();
5257 ddraw = create_ddraw();
5258 ok(!!ddraw, "Failed to create a ddraw object.\n");
5260 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5261 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
5263 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5265 /* Creating a flippable texture induces a BSoD on some versions of the
5266 * Intel graphics driver. At least Intel GMA 950 with driver version
5267 * 6.14.10.4926 on Windows XP SP3 is affected. */
5268 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
5270 win_skip("Skipping flippable texture test.\n");
5271 continue;
5274 memset(&surface_desc, 0, sizeof(surface_desc));
5275 surface_desc.dwSize = sizeof(surface_desc);
5276 surface_desc.dwFlags = DDSD_CAPS;
5277 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
5278 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5279 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
5280 surface_desc.dwWidth = 512;
5281 surface_desc.dwHeight = 512;
5282 surface_desc.dwBackBufferCount = 3;
5283 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5284 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5286 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
5287 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5288 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5289 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5291 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
5292 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
5293 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5294 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5296 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
5297 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5298 todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
5299 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#lx.\n", test_data[i].name, hr);
5300 if (FAILED(hr))
5301 continue;
5303 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
5304 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#lx.\n", test_data[i].name, hr);
5305 hr = IDirectDrawSurface_IsLost(frontbuffer);
5306 ok(hr == DD_OK, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5307 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
5308 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
5309 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5310 else
5311 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
5312 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5313 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#lx.\n", test_data[i].name, hr);
5314 hr = IDirectDrawSurface_IsLost(frontbuffer);
5315 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5316 hr = restore_surfaces(ddraw);
5317 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#lx.\n", test_data[i].name, hr);
5319 memset(&surface_desc, 0, sizeof(surface_desc));
5320 surface_desc.dwSize = sizeof(surface_desc);
5321 hr = IDirectDrawSurface_GetSurfaceDesc(frontbuffer, &surface_desc);
5322 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#lx.\n", test_data[i].name, hr);
5323 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
5324 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
5325 expected_caps |= DDSCAPS_VISIBLE;
5326 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5327 "%s: Got unexpected caps %#lx.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5328 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
5330 hr = IDirectDrawSurface_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
5331 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#lx.\n", test_data[i].name, hr);
5332 memset(&surface_desc, 0, sizeof(surface_desc));
5333 surface_desc.dwSize = sizeof(surface_desc);
5334 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer1, &surface_desc);
5335 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#lx.\n", test_data[i].name, hr);
5336 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %lu.\n",
5337 test_data[i].name, surface_desc.dwBackBufferCount);
5338 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
5339 expected_caps |= DDSCAPS_BACKBUFFER;
5340 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5341 "%s: Got unexpected caps %#lx.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5343 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
5344 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#lx.\n", test_data[i].name, hr);
5345 memset(&surface_desc, 0, sizeof(surface_desc));
5346 surface_desc.dwSize = sizeof(surface_desc);
5347 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer2, &surface_desc);
5348 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#lx.\n", test_data[i].name, hr);
5349 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %lu.\n",
5350 test_data[i].name, surface_desc.dwBackBufferCount);
5351 expected_caps &= ~DDSCAPS_BACKBUFFER;
5352 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5353 "%s: Got unexpected caps %#lx.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5355 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
5356 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#lx.\n", test_data[i].name, hr);
5357 memset(&surface_desc, 0, sizeof(surface_desc));
5358 surface_desc.dwSize = sizeof(surface_desc);
5359 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer3, &surface_desc);
5360 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#lx.\n", test_data[i].name, hr);
5361 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %lu.\n",
5362 test_data[i].name, surface_desc.dwBackBufferCount);
5363 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5364 "%s: Got unexpected caps %#lx.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5366 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer3, &caps, &surface);
5367 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#lx.\n", test_data[i].name, hr);
5368 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
5369 test_data[i].name, surface, frontbuffer);
5370 IDirectDrawSurface_Release(surface);
5372 memset(&surface_desc, 0, sizeof(surface_desc));
5373 surface_desc.dwSize = sizeof(surface_desc);
5374 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5375 surface_desc.ddsCaps.dwCaps = 0;
5376 surface_desc.dwWidth = 640;
5377 surface_desc.dwHeight = 480;
5378 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5379 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#lx.\n", test_data[i].name, hr);
5380 hr = IDirectDrawSurface_Flip(frontbuffer, surface, DDFLIP_WAIT);
5381 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5382 IDirectDrawSurface_Release(surface);
5384 hr = IDirectDrawSurface_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
5385 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5386 hr = IDirectDrawSurface_Flip(backbuffer1, NULL, DDFLIP_WAIT);
5387 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5388 hr = IDirectDrawSurface_Flip(backbuffer2, NULL, DDFLIP_WAIT);
5389 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5390 hr = IDirectDrawSurface_Flip(backbuffer3, NULL, DDFLIP_WAIT);
5391 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5393 /* The Nvidia Geforce 7 driver cannot do a color fill on a texture backbuffer after
5394 * the backbuffer has been locked or GetSurfaceDesc has been called. Do it ourselves
5395 * as a workaround. */
5396 fill_surface(backbuffer1, 0xffff0000);
5397 fill_surface(backbuffer2, 0xff00ff00);
5398 fill_surface(backbuffer3, 0xff0000ff);
5400 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
5401 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
5402 color = get_surface_color(backbuffer1, 320, 240);
5403 /* The testbot seems to just copy the contents of one surface to all the
5404 * others, instead of properly flipping. */
5405 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
5406 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5407 color = get_surface_color(backbuffer2, 320, 240);
5408 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5409 fill_surface(backbuffer3, 0xffff0000);
5411 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
5412 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
5413 color = get_surface_color(backbuffer1, 320, 240);
5414 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
5415 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5416 color = get_surface_color(backbuffer2, 320, 240);
5417 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5418 fill_surface(backbuffer3, 0xff00ff00);
5420 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
5421 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
5422 color = get_surface_color(backbuffer1, 320, 240);
5423 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
5424 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5425 color = get_surface_color(backbuffer2, 320, 240);
5426 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5427 fill_surface(backbuffer3, 0xff0000ff);
5429 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
5430 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
5431 color = get_surface_color(backbuffer2, 320, 240);
5432 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
5433 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5434 color = get_surface_color(backbuffer3, 320, 240);
5435 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5436 fill_surface(backbuffer1, 0xffff0000);
5438 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
5439 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
5440 color = get_surface_color(backbuffer1, 320, 240);
5441 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5442 color = get_surface_color(backbuffer3, 320, 240);
5443 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
5444 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5445 fill_surface(backbuffer2, 0xff00ff00);
5447 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
5448 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
5449 color = get_surface_color(backbuffer1, 320, 240);
5450 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
5451 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5452 color = get_surface_color(backbuffer2, 320, 240);
5453 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5455 IDirectDrawSurface_Release(backbuffer3);
5456 IDirectDrawSurface_Release(backbuffer2);
5457 IDirectDrawSurface_Release(backbuffer1);
5458 IDirectDrawSurface_Release(frontbuffer);
5461 refcount = IDirectDraw_Release(ddraw);
5462 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
5463 DestroyWindow(window);
5466 static void test_sysmem_overlay(void)
5468 IDirectDraw *ddraw;
5469 HWND window;
5470 HRESULT hr;
5471 DDSURFACEDESC ddsd;
5472 IDirectDrawSurface *surface;
5473 ULONG ref;
5475 window = create_window();
5476 ddraw = create_ddraw();
5477 ok(!!ddraw, "Failed to create a ddraw object.\n");
5479 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5480 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
5482 memset(&ddsd, 0, sizeof(ddsd));
5483 ddsd.dwSize = sizeof(ddsd);
5484 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
5485 ddsd.dwWidth = 16;
5486 ddsd.dwHeight = 16;
5487 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
5488 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5489 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5490 ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
5491 ddsd.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
5492 ddsd.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
5493 ddsd.ddpfPixelFormat.dwBBitMask = 0x000000ff;
5494 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
5495 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#lx.\n", hr);
5497 ref = IDirectDraw_Release(ddraw);
5498 ok(!ref, "Unexpected refcount %lu.\n", ref);
5499 DestroyWindow(window);
5502 static void test_primary_palette(void)
5504 DDSCAPS surface_caps = {DDSCAPS_FLIP};
5505 IDirectDrawSurface *primary, *backbuffer;
5506 PALETTEENTRY palette_entries[256];
5507 IDirectDrawPalette *palette, *tmp;
5508 DDSURFACEDESC surface_desc;
5509 IDirectDraw *ddraw;
5510 DWORD palette_caps;
5511 ULONG refcount;
5512 HWND window;
5513 HRESULT hr;
5515 window = create_window();
5516 ddraw = create_ddraw();
5517 ok(!!ddraw, "Failed to create a ddraw object.\n");
5518 if (FAILED(IDirectDraw_SetDisplayMode(ddraw, 640, 480, 8)))
5520 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
5521 IDirectDraw_Release(ddraw);
5522 DestroyWindow(window);
5523 return;
5525 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5526 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
5528 memset(&surface_desc, 0, sizeof(surface_desc));
5529 surface_desc.dwSize = sizeof(surface_desc);
5530 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
5531 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
5532 surface_desc.dwBackBufferCount = 1;
5533 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
5534 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
5535 hr = IDirectDrawSurface_GetAttachedSurface(primary, &surface_caps, &backbuffer);
5536 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#lx.\n", hr);
5538 memset(palette_entries, 0, sizeof(palette_entries));
5539 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
5540 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
5541 refcount = get_refcount((IUnknown *)palette);
5542 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
5544 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5545 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#lx.\n", hr);
5546 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#lx.\n", palette_caps);
5548 hr = IDirectDrawSurface_SetPalette(primary, palette);
5549 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
5551 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
5552 * and is generally somewhat broken with respect to 8 bpp / palette
5553 * handling. */
5554 if (SUCCEEDED(IDirectDrawSurface_GetPalette(backbuffer, &tmp)))
5556 win_skip("Broken palette handling detected, skipping tests.\n");
5557 IDirectDrawPalette_Release(tmp);
5558 IDirectDrawPalette_Release(palette);
5559 /* The Windows 8 testbot keeps extra references to the primary and
5560 * backbuffer while in 8 bpp mode. */
5561 hr = IDirectDraw_RestoreDisplayMode(ddraw);
5562 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#lx.\n", hr);
5563 goto done;
5566 refcount = get_refcount((IUnknown *)palette);
5567 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
5569 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5570 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#lx.\n", hr);
5571 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
5572 "Got unexpected palette caps %#lx.\n", palette_caps);
5574 hr = IDirectDrawSurface_SetPalette(primary, NULL);
5575 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
5576 refcount = get_refcount((IUnknown *)palette);
5577 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
5579 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5580 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#lx.\n", hr);
5581 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#lx.\n", palette_caps);
5583 hr = IDirectDrawSurface_SetPalette(primary, palette);
5584 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
5585 refcount = get_refcount((IUnknown *)palette);
5586 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
5588 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
5589 ok(SUCCEEDED(hr), "Failed to get palette, hr %#lx.\n", hr);
5590 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
5591 IDirectDrawPalette_Release(tmp);
5592 hr = IDirectDrawSurface_GetPalette(backbuffer, &tmp);
5593 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#lx.\n", hr);
5595 refcount = IDirectDrawPalette_Release(palette);
5596 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
5597 refcount = IDirectDrawPalette_Release(palette);
5598 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
5600 /* Note that this only seems to work when the palette is attached to the
5601 * primary surface. When attached to a regular surface, attempting to get
5602 * the palette here will cause an access violation. */
5603 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
5604 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#lx.\n", hr);
5606 hr = IDirectDrawSurface_IsLost(primary);
5607 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
5609 memset(&surface_desc, 0, sizeof(surface_desc));
5610 surface_desc.dwSize = sizeof(surface_desc);
5611 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
5612 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
5613 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %lu.\n", surface_desc.dwWidth);
5614 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %lu.\n", surface_desc.dwHeight);
5615 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == 8, "Got unexpected bit count %lu.\n",
5616 surface_desc.ddpfPixelFormat.dwRGBBitCount);
5618 hr = set_display_mode(ddraw, 640, 480);
5619 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
5621 memset(&surface_desc, 0, sizeof(surface_desc));
5622 surface_desc.dwSize = sizeof(surface_desc);
5623 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
5624 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
5625 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %lu.\n", surface_desc.dwWidth);
5626 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %lu.\n", surface_desc.dwHeight);
5627 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == 32
5628 || surface_desc.ddpfPixelFormat.dwRGBBitCount == 24,
5629 "Got unexpected bit count %lu.\n", surface_desc.ddpfPixelFormat.dwRGBBitCount);
5631 hr = IDirectDrawSurface_IsLost(primary);
5632 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
5633 hr = IDirectDrawSurface_Restore(primary);
5634 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
5635 hr = IDirectDrawSurface_IsLost(primary);
5636 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
5638 memset(&surface_desc, 0, sizeof(surface_desc));
5639 surface_desc.dwSize = sizeof(surface_desc);
5640 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
5641 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
5642 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %lu.\n", surface_desc.dwWidth);
5643 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %lu.\n", surface_desc.dwHeight);
5644 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == 32
5645 || surface_desc.ddpfPixelFormat.dwRGBBitCount == 24,
5646 "Got unexpected bit count %lu.\n", surface_desc.ddpfPixelFormat.dwRGBBitCount);
5648 done:
5649 refcount = IDirectDrawSurface_Release(backbuffer);
5650 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
5651 refcount = IDirectDrawSurface_Release(primary);
5652 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
5653 refcount = IDirectDraw_Release(ddraw);
5654 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
5655 DestroyWindow(window);
5658 static HRESULT WINAPI surface_counter(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
5660 UINT *surface_count = context;
5662 ++(*surface_count);
5663 IDirectDrawSurface_Release(surface);
5665 return DDENUMRET_OK;
5668 static void test_surface_attachment(void)
5670 IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
5671 DDSCAPS caps = {DDSCAPS_TEXTURE};
5672 DDSURFACEDESC surface_desc;
5673 IDirectDraw *ddraw;
5674 UINT surface_count;
5675 ULONG refcount;
5676 HWND window;
5677 HRESULT hr;
5679 window = create_window();
5680 ddraw = create_ddraw();
5681 ok(!!ddraw, "Failed to create a ddraw object.\n");
5682 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5683 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
5685 memset(&surface_desc, 0, sizeof(surface_desc));
5686 surface_desc.dwSize = sizeof(surface_desc);
5687 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
5688 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
5689 surface_desc.dwMipMapCount = 3;
5690 surface_desc.dwWidth = 128;
5691 surface_desc.dwHeight = 128;
5692 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5693 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
5695 hr = IDirectDrawSurface_GetAttachedSurface(surface1, &caps, &surface2);
5696 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#lx.\n", hr);
5697 hr = IDirectDrawSurface_GetAttachedSurface(surface2, &caps, &surface3);
5698 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#lx.\n", hr);
5699 hr = IDirectDrawSurface_GetAttachedSurface(surface3, &caps, &surface4);
5700 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
5702 surface_count = 0;
5703 IDirectDrawSurface_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
5704 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
5705 surface_count = 0;
5706 IDirectDrawSurface_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
5707 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
5708 surface_count = 0;
5709 IDirectDrawSurface_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
5710 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
5712 memset(&surface_desc, 0, sizeof(surface_desc));
5713 surface_desc.dwSize = sizeof(surface_desc);
5714 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5715 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5716 surface_desc.dwWidth = 16;
5717 surface_desc.dwHeight = 16;
5718 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5719 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
5721 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
5722 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5723 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5724 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5725 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
5726 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5727 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
5728 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5729 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
5730 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5731 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
5732 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5734 IDirectDrawSurface_Release(surface4);
5736 memset(&surface_desc, 0, sizeof(surface_desc));
5737 surface_desc.dwSize = sizeof(surface_desc);
5738 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5739 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5740 surface_desc.dwWidth = 16;
5741 surface_desc.dwHeight = 16;
5742 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5743 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
5745 if (SUCCEEDED(hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4)))
5747 skip("Running on refrast, skipping some tests.\n");
5748 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface4);
5749 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
5751 else
5753 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5754 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5755 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5756 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
5757 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5758 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
5759 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5760 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
5761 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5762 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
5763 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5766 IDirectDrawSurface_Release(surface4);
5767 IDirectDrawSurface_Release(surface3);
5768 IDirectDrawSurface_Release(surface2);
5769 IDirectDrawSurface_Release(surface1);
5771 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5772 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
5774 /* Try a single primary and two offscreen plain surfaces. */
5775 memset(&surface_desc, 0, sizeof(surface_desc));
5776 surface_desc.dwSize = sizeof(surface_desc);
5777 surface_desc.dwFlags = DDSD_CAPS;
5778 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
5779 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5780 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
5782 memset(&surface_desc, 0, sizeof(surface_desc));
5783 surface_desc.dwSize = sizeof(surface_desc);
5784 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5785 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5786 surface_desc.dwWidth = registry_mode.dmPelsWidth;
5787 surface_desc.dwHeight = registry_mode.dmPelsHeight;
5788 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
5789 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
5791 memset(&surface_desc, 0, sizeof(surface_desc));
5792 surface_desc.dwSize = sizeof(surface_desc);
5793 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5794 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5795 surface_desc.dwWidth = registry_mode.dmPelsWidth;
5796 surface_desc.dwHeight = registry_mode.dmPelsHeight;
5797 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
5798 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
5800 /* This one has a different size. */
5801 memset(&surface_desc, 0, sizeof(surface_desc));
5802 surface_desc.dwSize = sizeof(surface_desc);
5803 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5804 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5805 surface_desc.dwWidth = 128;
5806 surface_desc.dwHeight = 128;
5807 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5808 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
5810 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5811 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
5812 /* Try the reverse without detaching first. */
5813 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
5814 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#lx.\n", hr);
5815 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5816 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
5818 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
5819 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
5820 /* Try to detach reversed. */
5821 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5822 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5823 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
5824 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
5826 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
5827 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
5828 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
5829 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
5831 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
5832 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5833 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5834 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5836 IDirectDrawSurface_Release(surface4);
5837 IDirectDrawSurface_Release(surface3);
5838 IDirectDrawSurface_Release(surface2);
5839 IDirectDrawSurface_Release(surface1);
5841 /* Test depth surfaces of different sizes. */
5842 memset(&surface_desc, 0, sizeof(surface_desc));
5843 surface_desc.dwSize = sizeof(surface_desc);
5844 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5845 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5846 surface_desc.dwWidth = 64;
5847 surface_desc.dwHeight = 64;
5848 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5849 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
5851 memset(&surface_desc, 0, sizeof(surface_desc));
5852 surface_desc.dwSize = sizeof(surface_desc);
5853 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
5854 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
5855 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5856 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
5857 surface_desc.ddpfPixelFormat.dwZBufferBitDepth = 16;
5858 surface_desc.ddpfPixelFormat.dwZBitMask = 0x0000ffff;
5859 surface_desc.dwWidth = 32;
5860 surface_desc.dwHeight = 32;
5861 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
5862 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
5863 surface_desc.dwWidth = 64;
5864 surface_desc.dwHeight = 64;
5865 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
5866 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
5867 surface_desc.dwWidth = 128;
5868 surface_desc.dwHeight = 128;
5869 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5870 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
5872 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5873 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5874 if (SUCCEEDED(hr))
5875 IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5876 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface3);
5877 ok(hr == D3D_OK, "Failed to attach depth buffer, hr %#lx.\n", hr);
5878 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface3);
5879 ok(hr == D3D_OK, "Failed to detach depth buffer, hr %#lx.\n", hr);
5880 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
5881 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
5883 IDirectDrawSurface_Release(surface4);
5884 IDirectDrawSurface_Release(surface3);
5885 IDirectDrawSurface_Release(surface2);
5886 IDirectDrawSurface_Release(surface1);
5888 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
5889 memset(&surface_desc, 0, sizeof(surface_desc));
5890 surface_desc.dwSize = sizeof(surface_desc);
5891 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5892 surface_desc.dwWidth = 64;
5893 surface_desc.dwHeight = 64;
5894 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5895 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5896 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
5897 surface_desc.ddpfPixelFormat.dwRGBBitCount = 16;
5898 surface_desc.ddpfPixelFormat.dwRBitMask = 0xf800;
5899 surface_desc.ddpfPixelFormat.dwGBitMask = 0x07e0;
5900 surface_desc.ddpfPixelFormat.dwBBitMask = 0x001f;
5901 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5902 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
5903 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
5904 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
5906 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
5907 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
5908 surface_desc.ddpfPixelFormat.dwZBufferBitDepth = 16;
5909 surface_desc.ddpfPixelFormat.dwZBitMask = 0x0000ffff;
5910 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
5911 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
5913 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5914 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
5915 refcount = get_refcount((IUnknown *)surface2);
5916 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
5917 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5918 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#lx.\n", hr);
5920 /* Attaching while already attached to other surface. */
5921 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
5922 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
5923 hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
5924 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
5925 IDirectDrawSurface_Release(surface3);
5927 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5928 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
5929 refcount = get_refcount((IUnknown *)surface2);
5930 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
5932 /* Automatic detachment on release. */
5933 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5934 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
5935 refcount = get_refcount((IUnknown *)surface2);
5936 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
5937 refcount = IDirectDrawSurface_Release(surface1);
5938 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
5939 refcount = IDirectDrawSurface_Release(surface2);
5940 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
5941 refcount = IDirectDraw_Release(ddraw);
5942 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
5943 DestroyWindow(window);
5946 static void test_pixel_format(void)
5948 HWND window, window2, window3;
5949 HMODULE gl = NULL;
5950 int format, test_format;
5951 PIXELFORMATDESCRIPTOR pfd;
5952 IDirectDraw *ddraw = NULL;
5953 IDirectDrawClipper *clipper = NULL;
5954 HDC hdc, hdc2, hdc3;
5955 DDSURFACEDESC ddsd;
5956 IDirectDrawSurface *primary = NULL, *offscreen;
5957 ULONG refcount;
5958 DDBLTFX fx;
5959 HRESULT hr;
5960 BOOL ret;
5962 window = create_window();
5963 ok(!!window, "Failed to create window.\n");
5964 window2 = create_window();
5965 ok(!!window2, "Failed to create window.\n");
5967 hdc = GetDC(window);
5968 ok(!!hdc, "Failed to get DC.\n");
5969 hdc2 = GetDC(window2);
5970 ok(!!hdc2, "Failed to get DC.\n");
5972 gl = LoadLibraryA("opengl32.dll");
5973 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
5975 format = GetPixelFormat(hdc);
5976 ok(format == 0, "new window has pixel format %d\n", format);
5978 ZeroMemory(&pfd, sizeof(pfd));
5979 pfd.nSize = sizeof(pfd);
5980 pfd.nVersion = 1;
5981 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
5982 pfd.iPixelType = PFD_TYPE_RGBA;
5983 pfd.iLayerType = PFD_MAIN_PLANE;
5984 format = ChoosePixelFormat(hdc, &pfd);
5985 if (format <= 0)
5987 skip("no pixel format available\n");
5988 goto cleanup;
5991 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
5993 skip("failed to set pixel format\n");
5994 goto cleanup;
5997 if (!SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
5999 skip("failed to set pixel format on second window\n");
6000 goto cleanup;
6003 ddraw = create_ddraw();
6004 ok(!!ddraw, "Failed to create a ddraw object.\n");
6006 test_format = GetPixelFormat(hdc);
6007 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6009 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6010 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6012 test_format = GetPixelFormat(hdc);
6013 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6015 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
6016 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
6017 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
6018 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
6020 test_format = GetPixelFormat(hdc);
6021 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6022 test_format = GetPixelFormat(hdc2);
6023 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6025 memset(&ddsd, 0, sizeof(ddsd));
6026 ddsd.dwSize = sizeof(ddsd);
6027 ddsd.dwFlags = DDSD_CAPS;
6028 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
6030 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
6031 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
6033 test_format = GetPixelFormat(hdc);
6034 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6035 test_format = GetPixelFormat(hdc2);
6036 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6038 hr = IDirectDrawSurface_SetClipper(primary, clipper);
6039 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
6041 test_format = GetPixelFormat(hdc);
6042 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6043 test_format = GetPixelFormat(hdc2);
6044 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6046 memset(&ddsd, 0, sizeof(ddsd));
6047 ddsd.dwSize = sizeof(ddsd);
6048 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6049 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6050 ddsd.dwWidth = ddsd.dwHeight = 64;
6051 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &offscreen, NULL);
6052 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
6054 memset(&fx, 0, sizeof(fx));
6055 fx.dwSize = sizeof(fx);
6056 hr = IDirectDrawSurface_Blt(offscreen, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
6057 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#lx.\n", hr);
6059 test_format = GetPixelFormat(hdc);
6060 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6062 hr = IDirectDrawSurface_Blt(primary, NULL, offscreen, NULL, DDBLT_WAIT, NULL);
6063 ok(SUCCEEDED(hr), "Failed to blit to primary surface, hr %#lx.\n", hr);
6065 test_format = GetPixelFormat(hdc);
6066 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6067 test_format = GetPixelFormat(hdc2);
6068 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6070 IDirectDrawSurface_Release(offscreen);
6071 IDirectDrawSurface_Release(primary);
6072 refcount = IDirectDrawClipper_Release(clipper);
6073 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
6074 refcount = IDirectDraw_Release(ddraw);
6075 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
6077 /* Test that creating a device doesn't set a pixel format on a window which
6078 * never had one. */
6080 window3 = create_window();
6081 hdc3 = GetDC(window3);
6083 test_format = GetPixelFormat(hdc3);
6084 ok(!test_format, "Expected no format, got %d.\n", test_format);
6086 ddraw = create_ddraw();
6087 ok(!!ddraw, "Failed to create a ddraw object.\n");
6088 hr = IDirectDraw_SetCooperativeLevel(ddraw, window3, DDSCL_NORMAL);
6089 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6091 test_format = GetPixelFormat(hdc3);
6092 ok(!test_format, "Expected no format, got %d.\n", test_format);
6094 memset(&ddsd, 0, sizeof(ddsd));
6095 ddsd.dwSize = sizeof(ddsd);
6096 ddsd.dwFlags = DDSD_CAPS;
6097 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
6098 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
6099 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6101 memset(&ddsd, 0, sizeof(ddsd));
6102 ddsd.dwSize = sizeof(ddsd);
6103 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6104 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6105 ddsd.dwWidth = ddsd.dwHeight = 64;
6106 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &offscreen, NULL);
6107 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
6109 memset(&fx, 0, sizeof(fx));
6110 fx.dwSize = sizeof(fx);
6111 hr = IDirectDrawSurface_Blt(offscreen, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
6112 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#lx.\n", hr);
6114 hr = IDirectDrawSurface_Blt(primary, NULL, offscreen, NULL, DDBLT_WAIT, NULL);
6115 ok(SUCCEEDED(hr), "Failed to blit to primary surface, hr %#lx.\n", hr);
6117 test_format = GetPixelFormat(hdc3);
6118 ok(!test_format, "Expected no format, got %d.\n", test_format);
6120 IDirectDrawSurface_Release(offscreen);
6121 IDirectDrawSurface_Release(primary);
6122 refcount = IDirectDraw_Release(ddraw);
6123 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
6125 test_format = GetPixelFormat(hdc3);
6126 ok(!test_format, "Expected no format, got %d.\n", test_format);
6128 ret = SetPixelFormat(hdc3, format, &pfd);
6129 ok(ret, "Failed to set pixel format %d.\n", format);
6131 test_format = GetPixelFormat(hdc3);
6132 ok(test_format == format, "Expected pixel format %d, got %d.\n", format, test_format);
6134 ReleaseDC(window3, hdc3);
6135 DestroyWindow(window3);
6137 cleanup:
6138 FreeLibrary(gl);
6139 ReleaseDC(window2, hdc2);
6140 ReleaseDC(window, hdc);
6141 DestroyWindow(window2);
6142 DestroyWindow(window);
6145 static void test_create_surface_pitch(void)
6147 IDirectDrawSurface *surface, *primary;
6148 DDSURFACEDESC surface_desc;
6149 DDCAPS caps1, caps2;
6150 IDirectDraw *ddraw;
6151 unsigned int i;
6152 ULONG refcount;
6153 HWND window;
6154 HRESULT hr;
6155 void *mem;
6157 static const struct
6159 DWORD caps;
6160 DWORD flags_in;
6161 DWORD pitch_in;
6162 HRESULT hr;
6163 DWORD flags_out;
6164 DWORD pitch_out32;
6165 DWORD pitch_out64;
6167 test_data[] =
6169 /* 0 */
6170 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6171 0, 0, DD_OK,
6172 DDSD_PITCH, 0x100, 0x100},
6173 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6174 DDSD_PITCH, 0x104, DD_OK,
6175 DDSD_PITCH, 0x100, 0x100},
6176 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6177 DDSD_PITCH, 0x0f8, DD_OK,
6178 DDSD_PITCH, 0x100, 0x100},
6179 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6180 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
6181 0, 0, 0 },
6182 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6183 0, 0, DD_OK,
6184 DDSD_PITCH, 0x100, 0x0fc},
6185 /* 5 */
6186 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6187 DDSD_PITCH, 0x104, DD_OK,
6188 DDSD_PITCH, 0x100, 0x0fc},
6189 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6190 DDSD_PITCH, 0x0f8, DD_OK,
6191 DDSD_PITCH, 0x100, 0x0fc},
6192 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6193 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
6194 DDSD_PITCH, 0x100, 0x0fc},
6195 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6196 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
6197 0, 0, 0 },
6198 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6199 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
6200 0, 0, 0 },
6201 /* 10 */
6202 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
6203 0, 0, DDERR_INVALIDCAPS,
6204 0, 0, 0 },
6205 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6206 0, 0, DD_OK,
6207 DDSD_PITCH, 0x100, 0 },
6208 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE,
6209 0, 0, DD_OK,
6210 DDSD_PITCH, 0x100, 0 },
6211 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6212 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
6213 0, 0, 0 },
6214 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
6215 0, 0, DDERR_INVALIDCAPS,
6216 0, 0, 0 },
6217 /* 15 */
6218 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6219 0, 0, DD_OK,
6220 DDSD_PITCH, 0x100, 0 },
6221 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
6222 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
6223 0, 0, 0 },
6224 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
6225 0, 0, DD_OK,
6226 DDSD_PITCH, 0x100, 0x0fc},
6227 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
6228 0, 0, DD_OK,
6229 DDSD_PITCH, 0x100, 0x100},
6231 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
6233 window = create_window();
6234 ddraw = create_ddraw();
6235 ok(!!ddraw, "Failed to create a ddraw object.\n");
6236 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
6237 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6239 mem = calloc((63 * 4) + 8, 63);
6241 /* We need a primary surface and exclusive mode for video memory accounting to work
6242 * right on Windows. Otherwise it gives us junk data, like creating a video memory
6243 * surface freeing up memory. */
6244 memset(&surface_desc, 0, sizeof(surface_desc));
6245 surface_desc.dwSize = sizeof(surface_desc);
6246 surface_desc.dwFlags = DDSD_CAPS;
6247 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
6248 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
6249 ok(SUCCEEDED(hr), "Failed to create a primary surface, hr %#lx.\n", hr);
6251 memset(&caps1, 0, sizeof(caps1));
6252 caps1.dwSize = sizeof(caps1);
6253 hr = IDirectDraw_GetCaps(ddraw, &caps1, NULL);
6254 ok(SUCCEEDED(hr), "Failed to get ddraw caps, hr %#lx.\n", hr);
6256 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6258 memset(&surface_desc, 0, sizeof(surface_desc));
6259 surface_desc.dwSize = sizeof(surface_desc);
6260 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
6261 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
6262 surface_desc.dwWidth = 63;
6263 surface_desc.dwHeight = 63;
6264 surface_desc.lPitch = test_data[i].pitch_in;
6265 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6266 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
6267 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
6268 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
6269 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
6270 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
6271 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6272 if (test_data[i].flags_in & DDSD_LPSURFACE)
6274 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
6275 ok(hr == expected_hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n", i, hr, expected_hr);
6276 surface_desc.lpSurface = mem;
6277 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6279 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
6280 continue;
6281 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n", i, hr, test_data[i].hr);
6282 if (FAILED(hr))
6283 continue;
6285 memset(&surface_desc, 0, sizeof(surface_desc));
6286 surface_desc.dwSize = sizeof(surface_desc);
6287 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
6288 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#lx.\n", i, hr);
6289 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
6290 "Test %u: Got unexpected flags %#lx, expected %#lx.\n",
6291 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
6292 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
6294 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
6295 todo_wine ok(surface_desc.lPitch == test_data[i].pitch_out64,
6296 "Test %u: Got unexpected pitch %#lx, expected %#lx.\n",
6297 i, surface_desc.lPitch, test_data[i].pitch_out64);
6298 else
6299 ok(surface_desc.lPitch == test_data[i].pitch_out32,
6300 "Test %u: Got unexpected pitch %#lx, expected %#lx.\n",
6301 i, surface_desc.lPitch, test_data[i].pitch_out32);
6303 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
6305 memset(&caps2, 0, sizeof(caps2));
6306 caps2.dwSize = sizeof(caps2);
6307 hr = IDirectDraw_GetCaps(ddraw, &caps2, NULL);
6308 ok(SUCCEEDED(hr), "Failed to get ddraw caps, hr %#lx.\n", hr);
6309 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
6311 /* Star Trek Starfleet Academy cares about this bit here: That creating a system memory
6312 * resource does not influence available video memory. */
6313 ok(caps2.dwVidMemFree == caps1.dwVidMemFree, "Free video memory changed from %#lx to %#lx, test %u.\n",
6314 caps1.dwVidMemFree, caps2.dwVidMemFree, i);
6316 else if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
6318 /* DDSCAPS_ALLOCONLOAD does not seem to delay video memory allocation, at least not on
6319 * modern Windows.
6321 * The amount of video memory consumed is different from what dwHeight * lPitch would
6322 * suggest, although not by much. */
6323 ok(caps2.dwVidMemFree < caps1.dwVidMemFree,
6324 "Expected free video memory to change, but it did not, test %u.\n", i);
6327 IDirectDrawSurface_Release(surface);
6329 hr = IDirectDraw_GetCaps(ddraw, &caps2, NULL);
6330 ok(SUCCEEDED(hr), "Failed to get ddraw caps, hr %#lx.\n", hr);
6331 ok(caps2.dwVidMemFree == caps1.dwVidMemFree, "Free video memory changed from %#lx to %#lx, test %u.\n",
6332 caps1.dwVidMemFree, caps2.dwVidMemFree, i);
6335 free(mem);
6336 refcount = IDirectDraw_Release(ddraw);
6337 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
6338 DestroyWindow(window);
6341 static void test_mipmap(void)
6343 IDirectDrawSurface *surface, *surface_base, *surface_mip;
6344 unsigned int i, mipmap_count;
6345 DDSURFACEDESC surface_desc;
6346 IDirectDraw *ddraw;
6347 ULONG refcount;
6348 HWND window;
6349 HRESULT hr;
6350 DDSCAPS caps = {DDSCAPS_COMPLEX};
6351 DDCAPS hal_caps;
6353 static const struct
6355 DWORD flags;
6356 DWORD caps;
6357 DWORD width;
6358 DWORD height;
6359 DWORD mipmap_count_in;
6360 HRESULT hr;
6361 DWORD mipmap_count_out;
6363 tests[] =
6365 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS},
6366 {0, DDSCAPS_COMPLEX, 128, 32, 0, DDERR_INVALIDCAPS},
6367 {0, DDSCAPS_MIPMAP | DDSCAPS_COMPLEX, 128, 32, 0, DDERR_INVALIDCAPS},
6368 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
6369 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX, 128, 32, 0, DDERR_INVALIDCAPS},
6370 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 6},
6371 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 6},
6373 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 1, DDERR_INVALIDCAPS},
6374 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 3, DDERR_INVALIDCAPS},
6375 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
6376 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS},
6379 window = create_window();
6380 ddraw = create_ddraw();
6381 ok(!!ddraw, "Failed to create a ddraw object.\n");
6382 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6383 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6385 memset(&hal_caps, 0, sizeof(hal_caps));
6386 hal_caps.dwSize = sizeof(hal_caps);
6387 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
6388 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
6389 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
6391 skip("Mipmapped textures not supported, skipping tests.\n");
6392 IDirectDraw_Release(ddraw);
6393 DestroyWindow(window);
6394 return;
6397 for (i = 0; i < ARRAY_SIZE(tests); ++i)
6399 memset(&surface_desc, 0, sizeof(surface_desc));
6400 surface_desc.dwSize = sizeof(surface_desc);
6401 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
6402 surface_desc.ddsCaps.dwCaps = tests[i].caps;
6403 surface_desc.dwWidth = tests[i].width;
6404 surface_desc.dwHeight = tests[i].height;
6405 if (tests[i].flags & DDSD_MIPMAPCOUNT)
6406 surface_desc.dwMipMapCount = tests[i].mipmap_count_in;
6407 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6408 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#lx.\n", i, hr);
6409 if (FAILED(hr))
6410 continue;
6412 memset(&surface_desc, 0, sizeof(surface_desc));
6413 surface_desc.dwSize = sizeof(surface_desc);
6414 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
6415 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#lx.\n", i, hr);
6416 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
6417 "Test %u: Got unexpected flags %#lx.\n", i, surface_desc.dwFlags);
6418 ok(surface_desc.dwMipMapCount == tests[i].mipmap_count_out,
6419 "Test %u: Got unexpected mipmap count %lu.\n", i, surface_desc.dwMipMapCount);
6421 surface_base = surface;
6422 IDirectDrawSurface2_AddRef(surface_base);
6423 mipmap_count = surface_desc.dwMipMapCount;
6424 while (mipmap_count > 1)
6426 hr = IDirectDrawSurface_GetAttachedSurface(surface_base, &caps, &surface_mip);
6427 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get attached surface, hr %#lx.\n", i, mipmap_count, hr);
6429 memset(&surface_desc, 0, sizeof(surface_desc));
6430 surface_desc.dwSize = sizeof(surface_desc);
6431 hr = IDirectDrawSurface_GetSurfaceDesc(surface_base, &surface_desc);
6432 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get surface desc, hr %#lx.\n", i, mipmap_count, hr);
6433 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
6434 "Test %u, %u: Got unexpected flags %#lx.\n", i, mipmap_count, surface_desc.dwFlags);
6435 ok(surface_desc.dwMipMapCount == mipmap_count,
6436 "Test %u, %u: Got unexpected mipmap count %lu.\n",
6437 i, mipmap_count, surface_desc.dwMipMapCount);
6439 memset(&surface_desc, 0, sizeof(surface_desc));
6440 surface_desc.dwSize = sizeof(surface_desc);
6441 hr = IDirectDrawSurface_Lock(surface_base, NULL, &surface_desc, 0, NULL);
6442 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#lx.\n", i, mipmap_count, hr);
6443 ok(surface_desc.dwMipMapCount == mipmap_count,
6444 "Test %u, %u: unexpected change of mipmap count %lu.\n",
6445 i, mipmap_count, surface_desc.dwMipMapCount);
6446 memset(&surface_desc, 0, sizeof(surface_desc));
6447 surface_desc.dwSize = sizeof(surface_desc);
6448 hr = IDirectDrawSurface_Lock(surface_mip, NULL, &surface_desc, 0, NULL);
6449 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#lx.\n", i, mipmap_count, hr);
6450 ok(surface_desc.dwMipMapCount == mipmap_count - 1,
6451 "Test %u, %u: Got unexpected child mipmap count %lu.\n", i, mipmap_count, surface_desc.dwMipMapCount);
6452 IDirectDrawSurface_Unlock(surface_mip, NULL);
6453 IDirectDrawSurface_Unlock(surface_base, NULL);
6455 IDirectDrawSurface_Release(surface_base);
6456 surface_base = surface_mip;
6457 --mipmap_count;
6459 IDirectDrawSurface_Release(surface_base);
6461 IDirectDrawSurface_Release(surface);
6464 refcount = IDirectDraw_Release(ddraw);
6465 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
6466 DestroyWindow(window);
6469 static void test_palette_complex(void)
6471 IDirectDrawSurface *surface, *mipmap, *tmp;
6472 DDSURFACEDESC surface_desc;
6473 IDirectDraw *ddraw;
6474 IDirectDrawPalette *palette, *palette2, *palette_mipmap;
6475 ULONG refcount;
6476 HWND window;
6477 HRESULT hr;
6478 DDSCAPS caps = {DDSCAPS_COMPLEX};
6479 DDCAPS hal_caps;
6480 PALETTEENTRY palette_entries[256];
6481 unsigned int i;
6482 HDC dc;
6483 RGBQUAD rgbquad;
6484 UINT count;
6486 window = create_window();
6487 ddraw = create_ddraw();
6488 ok(!!ddraw, "Failed to create a ddraw object.\n");
6489 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6490 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6492 memset(&hal_caps, 0, sizeof(hal_caps));
6493 hal_caps.dwSize = sizeof(hal_caps);
6494 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
6495 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
6496 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
6498 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
6499 IDirectDraw_Release(ddraw);
6500 DestroyWindow(window);
6501 return;
6504 memset(&surface_desc, 0, sizeof(surface_desc));
6505 surface_desc.dwSize = sizeof(surface_desc);
6506 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6507 surface_desc.dwWidth = 128;
6508 surface_desc.dwHeight = 128;
6509 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6510 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6511 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
6512 surface_desc.ddpfPixelFormat.dwRGBBitCount = 8;
6513 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6514 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6516 memset(palette_entries, 0, sizeof(palette_entries));
6517 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6518 palette_entries, &palette, NULL);
6519 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
6521 memset(palette_entries, 0, sizeof(palette_entries));
6522 palette_entries[1].peRed = 0xff;
6523 palette_entries[1].peGreen = 0x80;
6524 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6525 palette_entries, &palette_mipmap, NULL);
6526 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
6528 palette2 = (void *)0xdeadbeef;
6529 hr = IDirectDrawSurface_GetPalette(surface, &palette2);
6530 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#lx.\n", hr);
6531 ok(!palette2, "Got unexpected palette %p.\n", palette2);
6532 hr = IDirectDrawSurface_SetPalette(surface, palette);
6533 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
6534 hr = IDirectDrawSurface_GetPalette(surface, &palette2);
6535 ok(SUCCEEDED(hr), "Failed to get palette, hr %#lx.\n", hr);
6536 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
6537 IDirectDrawPalette_Release(palette2);
6539 mipmap = surface;
6540 IDirectDrawSurface_AddRef(mipmap);
6541 for (i = 0; i < 7; ++i)
6543 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
6544 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#lx.\n", i, hr);
6545 palette2 = (void *)0xdeadbeef;
6546 hr = IDirectDrawSurface_GetPalette(tmp, &palette2);
6547 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#lx, i %u.\n", hr, i);
6548 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
6550 hr = IDirectDrawSurface_SetPalette(tmp, palette_mipmap);
6551 ok(SUCCEEDED(hr), "Failed to set palette, i %u, hr %#lx.\n", i, hr);
6553 hr = IDirectDrawSurface_GetPalette(tmp, &palette2);
6554 ok(SUCCEEDED(hr), "Failed to get palette, i %u, hr %#lx.\n", i, hr);
6555 ok(palette_mipmap == palette2, "Got unexpected palette %p.\n", palette2);
6556 IDirectDrawPalette_Release(palette2);
6558 hr = IDirectDrawSurface_GetDC(tmp, &dc);
6559 ok(SUCCEEDED(hr), "Failed to get DC, i %u, hr %#lx.\n", i, hr);
6560 count = GetDIBColorTable(dc, 1, 1, &rgbquad);
6561 ok(count == 1, "Expected count 1, got %u.\n", count);
6562 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x.\n", rgbquad.rgbRed);
6563 ok(rgbquad.rgbGreen == 0x80, "Expected rgbGreen = 0x80, got %#x.\n", rgbquad.rgbGreen);
6564 ok(rgbquad.rgbBlue == 0x0, "Expected rgbBlue = 0x0, got %#x.\n", rgbquad.rgbBlue);
6565 hr = IDirectDrawSurface_ReleaseDC(tmp, dc);
6566 ok(SUCCEEDED(hr), "Failed to release DC, i %u, hr %#lx.\n", i, hr);
6568 IDirectDrawSurface_Release(mipmap);
6569 mipmap = tmp;
6572 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
6573 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
6574 IDirectDrawSurface_Release(mipmap);
6575 refcount = IDirectDrawSurface_Release(surface);
6576 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
6577 refcount = IDirectDrawPalette_Release(palette_mipmap);
6578 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
6579 refcount = IDirectDrawPalette_Release(palette);
6580 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
6582 refcount = IDirectDraw_Release(ddraw);
6583 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
6584 DestroyWindow(window);
6587 static void test_p8_blit(void)
6589 IDirectDrawSurface *src, *dst, *dst_p8;
6590 DDSURFACEDESC surface_desc;
6591 unsigned int color, x;
6592 IDirectDraw *ddraw;
6593 IDirectDrawPalette *palette, *palette2;
6594 ULONG refcount;
6595 HWND window;
6596 HRESULT hr;
6597 PALETTEENTRY palette_entries[256];
6598 DDBLTFX fx;
6599 BOOL is_warp;
6600 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
6601 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
6602 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
6603 static const unsigned int expected[] =
6605 0x00101010, 0x00010101, 0x00020202, 0x00030303,
6606 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
6609 window = create_window();
6610 ddraw = create_ddraw();
6611 ok(!!ddraw, "Failed to create a ddraw object.\n");
6612 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6613 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6614 is_warp = ddraw_is_warp(ddraw);
6616 memset(palette_entries, 0, sizeof(palette_entries));
6617 palette_entries[1].peGreen = 0xff;
6618 palette_entries[2].peBlue = 0xff;
6619 palette_entries[3].peFlags = 0xff;
6620 palette_entries[4].peRed = 0xff;
6621 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6622 palette_entries, &palette, NULL);
6623 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
6624 palette_entries[1].peBlue = 0xff;
6625 palette_entries[2].peGreen = 0xff;
6626 palette_entries[3].peRed = 0xff;
6627 palette_entries[4].peFlags = 0x0;
6628 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
6629 palette_entries, &palette2, NULL);
6630 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
6632 memset(&surface_desc, 0, sizeof(surface_desc));
6633 surface_desc.dwSize = sizeof(surface_desc);
6634 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6635 surface_desc.dwWidth = 8;
6636 surface_desc.dwHeight = 1;
6637 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6638 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6639 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
6640 surface_desc.ddpfPixelFormat.dwRGBBitCount = 8;
6641 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src, NULL);
6642 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6643 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
6644 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6645 hr = IDirectDrawSurface_SetPalette(dst_p8, palette2);
6646 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
6648 memset(&surface_desc, 0, sizeof(surface_desc));
6649 surface_desc.dwSize = sizeof(surface_desc);
6650 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6651 surface_desc.dwWidth = 8;
6652 surface_desc.dwHeight = 1;
6653 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6654 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6655 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
6656 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
6657 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
6658 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
6659 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
6660 surface_desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
6661 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst, NULL);
6662 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6664 memset(&surface_desc, 0, sizeof(surface_desc));
6665 surface_desc.dwSize = sizeof(surface_desc);
6666 hr = IDirectDrawSurface_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
6667 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#lx.\n", hr);
6668 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
6669 hr = IDirectDrawSurface_Unlock(src, NULL);
6670 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#lx.\n", hr);
6672 hr = IDirectDrawSurface_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
6673 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#lx.\n", hr);
6674 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
6675 hr = IDirectDrawSurface_Unlock(dst_p8, NULL);
6676 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#lx.\n", hr);
6678 fx.dwSize = sizeof(fx);
6679 fx.dwFillColor = 0xdeadbeef;
6680 hr = IDirectDrawSurface_Blt(dst, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
6681 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
6683 hr = IDirectDrawSurface_SetPalette(src, palette);
6684 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
6685 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
6686 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
6687 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
6688 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
6689 "Failed to blit, hr %#lx.\n", hr);
6691 if (SUCCEEDED(hr))
6693 for (x = 0; x < ARRAY_SIZE(expected); x++)
6695 color = get_surface_color(dst, x, 0);
6696 /* WARP on 1709 and newer write zeroes on non-colorkeyed P8 -> RGB blits. For ckey
6697 * blits see below. */
6698 todo_wine ok(compare_color(color, expected[x], 0)
6699 || broken(is_warp && compare_color(color, 0x00000000, 0)),
6700 "Pixel %u: Got color %#x, expected %#x.\n",
6701 x, color, expected[x]);
6705 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
6706 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
6707 hr = IDirectDrawSurface_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
6708 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
6710 hr = IDirectDrawSurface_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
6711 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#lx.\n", hr);
6712 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
6713 * surface untouched. Error checking (DDBLT_KEYSRC without a key
6714 * for example) also works as expected.
6716 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
6717 * the display mode set to P8 doesn't help either. */
6718 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
6719 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
6720 "Got unexpected P8 color key blit result.\n");
6721 hr = IDirectDrawSurface_Unlock(dst_p8, NULL);
6722 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#lx.\n", hr);
6724 IDirectDrawSurface_Release(src);
6725 IDirectDrawSurface_Release(dst);
6726 IDirectDrawSurface_Release(dst_p8);
6727 IDirectDrawPalette_Release(palette);
6728 IDirectDrawPalette_Release(palette2);
6730 refcount = IDirectDraw_Release(ddraw);
6731 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
6732 DestroyWindow(window);
6735 static void test_material(void)
6737 IDirect3DMaterial *background, *material;
6738 IDirect3DExecuteBuffer *execute_buffer;
6739 D3DMATERIALHANDLE mat_handle, tmp;
6740 D3DEXECUTEBUFFERDESC exec_desc;
6741 IDirect3DViewport *viewport;
6742 IDirect3DDevice *device;
6743 IDirectDrawSurface *rt;
6744 unsigned int color, i;
6745 IDirectDraw *ddraw;
6746 UINT inst_length;
6747 ULONG refcount;
6748 HWND window;
6749 HRESULT hr;
6750 BOOL valid;
6751 void *ptr;
6753 static D3DVERTEX quad[] =
6755 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6756 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6757 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6758 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
6760 static const struct
6762 BOOL material;
6763 D3DCOLOR expected_color;
6765 test_data[] =
6767 {TRUE, 0x0000ff00},
6768 {FALSE, 0x00ffffff},
6770 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
6772 window = create_window();
6773 ddraw = create_ddraw();
6774 ok(!!ddraw, "Failed to create a ddraw object.\n");
6775 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
6777 skip("Failed to create a 3D device, skipping test.\n");
6778 DestroyWindow(window);
6779 return;
6782 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
6783 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
6785 background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
6786 viewport = create_viewport(device, 0, 0, 640, 480);
6787 viewport_set_background(device, viewport, background);
6789 material = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
6790 hr = IDirect3DMaterial_GetHandle(material, device, &mat_handle);
6791 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#lx.\n", hr);
6793 memset(&exec_desc, 0, sizeof(exec_desc));
6794 exec_desc.dwSize = sizeof(exec_desc);
6795 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
6796 exec_desc.dwBufferSize = 1024;
6797 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
6799 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
6800 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#lx.\n", hr);
6802 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6804 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
6805 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#lx.\n", hr);
6807 memcpy(exec_desc.lpData, quad, sizeof(quad));
6808 ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad);
6809 emit_set_ls(&ptr, D3DLIGHTSTATE_MATERIAL, test_data[i].material ? mat_handle : 0);
6810 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
6811 emit_tquad(&ptr, 0);
6812 emit_end(&ptr);
6813 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
6814 inst_length -= sizeof(quad);
6816 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
6817 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#lx.\n", hr);
6819 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
6820 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
6822 hr = IDirect3DDevice_BeginScene(device);
6823 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
6824 set_execute_data(execute_buffer, 4, sizeof(quad), inst_length);
6825 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
6826 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#lx.\n", hr);
6827 hr = IDirect3DDevice_EndScene(device);
6828 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
6829 color = get_surface_color(rt, 320, 240);
6830 if (test_data[i].material)
6831 ok(compare_color(color, test_data[i].expected_color, 1)
6832 /* The Windows 8 testbot appears to return undefined results. */
6833 || broken(TRUE),
6834 "Got unexpected color 0x%08x, test %u.\n", color, i);
6835 else
6836 ok(compare_color(color, test_data[i].expected_color, 1),
6837 "Got unexpected color 0x%08x, test %u.\n", color, i);
6840 destroy_material(material);
6841 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
6842 hr = IDirect3DMaterial_GetHandle(material, device, &mat_handle);
6843 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#lx.\n", hr);
6845 hr = IDirect3DViewport_SetBackground(viewport, mat_handle);
6846 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#lx.\n", hr);
6847 hr = IDirect3DViewport_GetBackground(viewport, &tmp, &valid);
6848 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#lx.\n", hr);
6849 ok(tmp == mat_handle, "Got unexpected material handle %#lx, expected %#lx.\n", tmp, mat_handle);
6850 ok(valid, "Got unexpected valid %#x.\n", valid);
6851 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6852 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
6853 color = get_surface_color(rt, 320, 240);
6854 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
6856 hr = IDirect3DViewport_SetBackground(viewport, 0);
6857 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
6858 hr = IDirect3DViewport_GetBackground(viewport, &tmp, &valid);
6859 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#lx.\n", hr);
6860 ok(tmp == mat_handle, "Got unexpected material handle %#lx, expected %#lx.\n", tmp, mat_handle);
6861 ok(valid, "Got unexpected valid %#x.\n", valid);
6862 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6863 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
6864 color = get_surface_color(rt, 320, 240);
6865 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
6867 destroy_viewport(device, viewport);
6868 viewport = create_viewport(device, 0, 0, 640, 480);
6870 hr = IDirect3DViewport_GetBackground(viewport, &tmp, &valid);
6871 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#lx.\n", hr);
6872 ok(!tmp, "Got unexpected material handle %#lx.\n", tmp);
6873 ok(!valid, "Got unexpected valid %#x.\n", valid);
6874 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
6875 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
6876 color = get_surface_color(rt, 320, 240);
6877 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x.\n", color);
6879 IDirect3DExecuteBuffer_Release(execute_buffer);
6880 destroy_viewport(device, viewport);
6881 destroy_material(background);
6882 destroy_material(material);
6883 IDirectDrawSurface_Release(rt);
6884 refcount = IDirect3DDevice_Release(device);
6885 ok(!refcount, "Device has %lu references left.\n", refcount);
6886 refcount = IDirectDraw_Release(ddraw);
6887 ok(!refcount, "Ddraw object has %lu references left.\n", refcount);
6888 DestroyWindow(window);
6891 static void test_lighting(void)
6893 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
6894 static D3DMATRIX mat =
6896 1.0f, 0.0f, 0.0f, 0.0f,
6897 0.0f, 1.0f, 0.0f, 0.0f,
6898 0.0f, 0.0f, 1.0f, 0.0f,
6899 0.0f, 0.0f, 0.0f, 1.0f,
6901 mat_singular =
6903 1.0f, 0.0f, 1.0f, 0.0f,
6904 0.0f, 1.0f, 0.0f, 0.0f,
6905 1.0f, 0.0f, 1.0f, 0.0f,
6906 0.0f, 0.0f, 0.5f, 1.0f,
6908 mat_transf =
6910 0.0f, 0.0f, 1.0f, 0.0f,
6911 0.0f, 1.0f, 0.0f, 0.0f,
6912 -1.0f, 0.0f, 0.0f, 0.0f,
6913 10.f, 10.0f, 10.0f, 1.0f,
6915 mat_nonaffine =
6917 1.0f, 0.0f, 0.0f, 0.0f,
6918 0.0f, 1.0f, 0.0f, 0.0f,
6919 0.0f, 0.0f, 1.0f, -1.0f,
6920 10.f, 10.0f, 10.0f, 0.0f,
6922 static D3DLVERTEX unlitquad[] =
6924 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
6925 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
6926 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
6927 {{ 0.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
6929 litquad[] =
6931 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
6932 {{-1.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
6933 {{ 0.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
6934 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
6936 static D3DVERTEX unlitnquad[] =
6938 {{0.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6939 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6940 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6941 {{1.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6943 litnquad[] =
6945 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6946 {{0.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6947 {{1.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6948 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
6950 nquad[] =
6952 {{-1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6953 {{-1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6954 {{ 1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6955 {{ 1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6957 rotatedquad[] =
6959 {{-10.0f}, {-11.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
6960 {{-10.0f}, { -9.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
6961 {{-10.0f}, { -9.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
6962 {{-10.0f}, {-11.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
6964 translatedquad[] =
6966 {{-11.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6967 {{-11.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6968 {{ -9.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6969 {{ -9.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
6971 static const struct
6973 D3DMATRIX *world_matrix;
6974 void *quad;
6975 DWORD expected;
6976 const char *message;
6978 tests[] =
6980 {&mat, nquad, 0x000060ff, "Lit quad with light"},
6981 {&mat_singular, nquad, 0x00004db4, "Lit quad with singular world matrix"},
6982 {&mat_transf, rotatedquad, 0x000060ff, "Lit quad with transformation matrix"},
6983 {&mat_nonaffine, translatedquad, 0x000060ff, "Lit quad with non-affine matrix"},
6986 D3DMATRIXHANDLE world_handle, view_handle, proj_handle;
6987 IDirect3DViewport *viewport, *viewport2;
6988 IDirect3DExecuteBuffer *execute_buffer;
6989 unsigned int inst_length, color, i;
6990 D3DEXECUTEBUFFERDESC exec_desc;
6991 D3DMATERIALHANDLE mat_handle;
6992 IDirect3DMaterial *material;
6993 IDirect3DDevice *device;
6994 IDirectDrawSurface *rt;
6995 IDirect3DLight *light;
6996 D3DLIGHT light_desc;
6997 IDirectDraw *ddraw;
6998 ULONG refcount;
6999 IDirect3D *d3d;
7000 HWND window;
7001 HRESULT hr;
7002 void *ptr;
7004 window = create_window();
7005 ddraw = create_ddraw();
7006 ok(!!ddraw, "Failed to create a ddraw object.\n");
7007 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7009 skip("Failed to create a 3D device, skipping test.\n");
7010 IDirectDraw_Release(ddraw);
7011 DestroyWindow(window);
7012 return;
7015 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
7016 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7018 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
7019 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7021 viewport = create_viewport(device, 0, 0, 640, 480);
7022 material = create_diffuse_and_ambient_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
7023 viewport_set_background(device, viewport, material);
7025 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7026 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7028 hr = IDirect3DDevice_CreateMatrix(device, &world_handle);
7029 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7030 hr = IDirect3DDevice_SetMatrix(device, world_handle, &mat);
7031 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7032 hr = IDirect3DDevice_CreateMatrix(device, &view_handle);
7033 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7034 hr = IDirect3DDevice_SetMatrix(device, view_handle, &mat);
7035 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7036 hr = IDirect3DDevice_CreateMatrix(device, &proj_handle);
7037 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7038 hr = IDirect3DDevice_SetMatrix(device, proj_handle, &mat);
7039 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7041 memset(&exec_desc, 0, sizeof(exec_desc));
7042 exec_desc.dwSize = sizeof(exec_desc);
7043 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
7044 exec_desc.dwBufferSize = 1024;
7045 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
7047 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
7048 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7050 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
7051 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7053 memcpy(exec_desc.lpData, unlitquad, sizeof(unlitquad));
7054 ptr = ((BYTE *)exec_desc.lpData) + sizeof(unlitquad);
7055 emit_set_ts(&ptr, D3DTRANSFORMSTATE_WORLD, world_handle);
7056 emit_set_ts(&ptr, D3DTRANSFORMSTATE_VIEW, view_handle);
7057 emit_set_ts(&ptr, D3DTRANSFORMSTATE_PROJECTION, proj_handle);
7058 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, FALSE);
7059 emit_set_rs(&ptr, D3DRENDERSTATE_FOGENABLE, FALSE);
7060 emit_set_rs(&ptr, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
7061 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
7062 emit_tquad_tlist(&ptr, 0);
7063 emit_end(&ptr);
7064 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
7065 inst_length -= sizeof(unlitquad);
7067 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
7068 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7070 hr = IDirect3DDevice_BeginScene(device);
7071 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7073 set_execute_data(execute_buffer, 4, sizeof(unlitquad), inst_length);
7074 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
7075 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7077 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
7078 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7080 memcpy(exec_desc.lpData, litquad, sizeof(litquad));
7081 ptr = ((BYTE *)exec_desc.lpData) + sizeof(litquad);
7082 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
7083 emit_tquad_tlist(&ptr, 0);
7084 emit_end(&ptr);
7085 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
7086 inst_length -= sizeof(litquad);
7088 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
7089 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7091 set_execute_data(execute_buffer, 4, sizeof(litquad), inst_length);
7092 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
7093 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7095 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
7096 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7098 memcpy(exec_desc.lpData, unlitnquad, sizeof(unlitnquad));
7099 ptr = ((BYTE *)exec_desc.lpData) + sizeof(unlitnquad);
7100 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
7101 emit_tquad_tlist(&ptr, 0);
7102 emit_end(&ptr);
7103 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
7104 inst_length -= sizeof(unlitnquad);
7106 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
7107 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7109 set_execute_data(execute_buffer, 4, sizeof(unlitnquad), inst_length);
7110 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
7111 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7113 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
7114 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7116 memcpy(exec_desc.lpData, litnquad, sizeof(litnquad));
7117 ptr = ((BYTE *)exec_desc.lpData) + sizeof(litnquad);
7118 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
7119 emit_tquad_tlist(&ptr, 0);
7120 emit_end(&ptr);
7121 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
7122 inst_length -= sizeof(litnquad);
7124 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
7125 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7127 set_execute_data(execute_buffer, 4, sizeof(litnquad), inst_length);
7128 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
7129 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7131 hr = IDirect3DDevice_EndScene(device);
7132 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7134 color = get_surface_color(rt, 160, 360);
7135 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
7136 color = get_surface_color(rt, 160, 120);
7137 ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
7138 color = get_surface_color(rt, 480, 360);
7139 ok(color == 0x00ffffff, "Unlit quad with normals has color 0x%08x.\n", color);
7140 color = get_surface_color(rt, 480, 120);
7141 ok(color == 0x00ffffff, "Lit quad with normals has color 0x%08x.\n", color);
7143 hr = IDirect3DMaterial_GetHandle(material, device, &mat_handle);
7144 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7146 hr = IDirect3D_CreateLight(d3d, &light, NULL);
7147 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#lx.\n", hr);
7148 memset(&light_desc, 0, sizeof(light_desc));
7149 light_desc.dwSize = sizeof(light_desc);
7150 light_desc.dltType = D3DLIGHT_DIRECTIONAL;
7151 light_desc.dcvColor.r = 0.0f;
7152 light_desc.dcvColor.g = 0.25f;
7153 light_desc.dcvColor.b = 1.0f;
7154 light_desc.dcvColor.a = 1.0f;
7155 light_desc.dvDirection.z = 1.0f;
7156 hr = IDirect3DLight_SetLight(light, &light_desc);
7157 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7158 hr = IDirect3DViewport_AddLight(viewport, light);
7159 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7160 hr = IDirect3DViewport_AddLight(viewport, light);
7161 ok(hr == D3DERR_LIGHTHASVIEWPORT, "Got unexpected hr %#lx.\n", hr);
7163 viewport2 = create_viewport(device, 0, 0, 640, 480);
7164 hr = IDirect3DViewport_AddLight(viewport2, light);
7165 ok(hr == D3DERR_LIGHTHASVIEWPORT, "Got unexpected hr %#lx.\n", hr);
7166 destroy_viewport(device, viewport2);
7168 hr = IDirect3DViewport_DeleteLight(viewport, light);
7169 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7170 hr = IDirect3DViewport_AddLight(viewport, light);
7171 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7173 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7175 hr = IDirect3DDevice_SetMatrix(device, world_handle, tests[i].world_matrix);
7176 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7178 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7179 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7181 hr = IDirect3DDevice_BeginScene(device);
7182 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7184 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
7185 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7187 memcpy(exec_desc.lpData, tests[i].quad, sizeof(nquad));
7188 ptr = ((BYTE *)exec_desc.lpData) + sizeof(nquad);
7189 emit_set_ls(&ptr, D3DLIGHTSTATE_MATERIAL, mat_handle);
7190 emit_set_ls(&ptr, D3DLIGHTSTATE_AMBIENT, 0xff002000);
7191 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
7192 emit_tquad_tlist(&ptr, 0);
7193 emit_end(&ptr);
7194 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
7195 inst_length -= sizeof(nquad);
7197 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
7198 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7200 set_execute_data(execute_buffer, 4, sizeof(nquad), inst_length);
7201 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
7202 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7204 hr = IDirect3DDevice_EndScene(device);
7205 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7207 color = get_surface_color(rt, 320, 240);
7208 ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
7211 IDirect3DExecuteBuffer_Release(execute_buffer);
7212 IDirect3DDevice_DeleteMatrix(device, world_handle);
7213 IDirect3DDevice_DeleteMatrix(device, view_handle);
7214 IDirect3DDevice_DeleteMatrix(device, proj_handle);
7215 hr = IDirect3DViewport_DeleteLight(viewport, light);
7216 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7217 IDirect3DLight_Release(light);
7218 destroy_material(material);
7219 destroy_viewport(device, viewport);
7220 IDirectDrawSurface_Release(rt);
7221 refcount = IDirect3DDevice_Release(device);
7222 ok(!refcount, "Device has %lu references left.\n", refcount);
7223 IDirect3D_Release(d3d);
7224 refcount = IDirectDraw_Release(ddraw);
7225 ok(!refcount, "Ddraw object has %lu references left.\n", refcount);
7226 DestroyWindow(window);
7229 static void test_specular_lighting(void)
7231 static const unsigned int vertices_side = 5;
7232 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
7233 const unsigned int vertex_count = vertices_side * vertices_side;
7234 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
7235 static D3DMATRIX mat =
7237 1.0f, 0.0f, 0.0f, 0.0f,
7238 0.0f, 1.0f, 0.0f, 0.0f,
7239 0.0f, 0.0f, 1.0f, 0.0f,
7240 0.0f, 0.0f, 0.0f, 1.0f,
7242 /* Use of D3DLIGHT2 instead of D3DLIGHT is intentional. Using D3DLIGHT
7243 * without dwFlags looks broken on Windows 7: directional light behaves as
7244 * if _LOCALVIEWER state is off, point and spot lights do not work at all
7245 * and always output zero colours. */
7246 static D3DLIGHT2 directional =
7248 sizeof(D3DLIGHT2),
7249 D3DLIGHT_DIRECTIONAL,
7250 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7251 {{0.0f}, {0.0f}, {0.0f}},
7252 {{0.0f}, {0.0f}, {1.0f}},
7254 point =
7256 sizeof(D3DLIGHT2),
7257 D3DLIGHT_POINT,
7258 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7259 {{0.0f}, {0.0f}, {0.0f}},
7260 {{0.0f}, {0.0f}, {0.0f}},
7261 100.0f,
7262 0.0f,
7263 0.0f, 0.0f, 1.0f,
7265 spot =
7267 sizeof(D3DLIGHT2),
7268 D3DLIGHT_SPOT,
7269 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7270 {{0.0f}, {0.0f}, {0.0f}},
7271 {{0.0f}, {0.0f}, {1.0f}},
7272 100.0f,
7273 1.0f,
7274 0.0f, 0.0f, 1.0f,
7275 M_PI / 12.0f, M_PI / 3.0f
7277 parallelpoint =
7279 sizeof(D3DLIGHT2),
7280 D3DLIGHT_PARALLELPOINT,
7281 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7282 {{0.5f}, {0.0f}, {-1.0f}},
7283 {{0.0f}, {0.0f}, {0.0f}},
7285 point_side =
7287 sizeof(D3DLIGHT2),
7288 D3DLIGHT_POINT,
7289 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7290 {{-1.1f}, {0.0f}, {1.1f}},
7291 {{0.0f}, {0.0f}, {0.0f}},
7292 100.0f,
7293 0.0f,
7294 1.0f, 0.0f, 0.0f,
7296 point_far =
7298 sizeof(D3DLIGHT2),
7299 D3DLIGHT_POINT,
7300 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7301 {{0.0f}, {0.0f}, {0.1f}},
7302 {{0.0f}, {0.0f}, {0.0f}},
7303 1.0f,
7304 0.0f,
7305 1.0f, 0.0f, 0.0f,
7307 static const struct expected_color
7309 unsigned int x, y, colour;
7311 expected_directional_local[] =
7313 {160, 120, 0x003c3c3c},
7314 {320, 120, 0x00717171},
7315 {480, 120, 0x003c3c3c},
7316 {160, 240, 0x00717171},
7317 {320, 240, 0x00ffffff},
7318 {480, 240, 0x00717171},
7319 {160, 360, 0x003c3c3c},
7320 {320, 360, 0x00717171},
7321 {480, 360, 0x003c3c3c},
7323 expected_point_local[] =
7325 {160, 120, 0x00000000},
7326 {320, 120, 0x00090909},
7327 {480, 120, 0x00000000},
7328 {160, 240, 0x00090909},
7329 {320, 240, 0x00fafafa},
7330 {480, 240, 0x00090909},
7331 {160, 360, 0x00000000},
7332 {320, 360, 0x00090909},
7333 {480, 360, 0x00000000},
7335 expected_spot_local[] =
7337 {160, 120, 0x00000000},
7338 {320, 120, 0x00020202},
7339 {480, 120, 0x00000000},
7340 {160, 240, 0x00020202},
7341 {320, 240, 0x00fafafa},
7342 {480, 240, 0x00020202},
7343 {160, 360, 0x00000000},
7344 {320, 360, 0x00020202},
7345 {480, 360, 0x00000000},
7347 expected_parallelpoint[] =
7349 {160, 120, 0x00050505},
7350 {320, 120, 0x002c2c2c},
7351 {480, 120, 0x006e6e6e},
7352 {160, 240, 0x00090909},
7353 {320, 240, 0x00717171},
7354 {480, 240, 0x00ffffff},
7355 {160, 360, 0x00050505},
7356 {320, 360, 0x002c2c2c},
7357 {480, 360, 0x006e6e6e},
7359 expected_point_far[] =
7361 {160, 120, 0x00000000},
7362 {320, 120, 0x00000000},
7363 {480, 120, 0x00000000},
7364 {160, 240, 0x00000000},
7365 {320, 240, 0x00ffffff},
7366 {480, 240, 0x00000000},
7367 {160, 360, 0x00000000},
7368 {320, 360, 0x00000000},
7369 {480, 360, 0x00000000},
7371 expected_zero[] =
7373 {160, 120, 0x00000000},
7374 {320, 120, 0x00000000},
7375 {480, 120, 0x00000000},
7376 {160, 240, 0x00000000},
7377 {320, 240, 0x00000000},
7378 {480, 240, 0x00000000},
7379 {160, 360, 0x00000000},
7380 {320, 360, 0x00000000},
7381 {480, 360, 0x00000000},
7383 static const struct
7385 D3DLIGHT2 *light;
7386 float specular_power;
7387 const struct expected_color *expected;
7388 unsigned int expected_count;
7390 tests[] =
7392 {&directional, 30.0f, expected_directional_local, ARRAY_SIZE(expected_directional_local)},
7393 {&point, 30.0f, expected_point_local, ARRAY_SIZE(expected_point_local)},
7394 {&spot, 30.0f, expected_spot_local, ARRAY_SIZE(expected_spot_local)},
7395 {&parallelpoint, 30.0f, expected_parallelpoint, ARRAY_SIZE(expected_parallelpoint)},
7396 {&point_side, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
7397 {&point_far, 1.0f, expected_point_far, ARRAY_SIZE(expected_point_far)},
7398 {&directional, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
7399 {&point, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
7400 {&spot, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
7401 {&parallelpoint, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
7402 {&point_far, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
7405 D3DMATRIXHANDLE world_handle, view_handle, proj_handle;
7406 IDirect3DMaterial *material, *background_material;
7407 unsigned int inst_length, colour, i, j, x, y;
7408 IDirect3DExecuteBuffer *execute_buffer;
7409 D3DEXECUTEBUFFERDESC exec_desc;
7410 D3DMATERIALHANDLE mat_handle;
7411 IDirect3DViewport *viewport;
7412 IDirect3DDevice *device;
7413 IDirectDrawSurface *rt;
7414 IDirect3DLight *light;
7415 IDirectDraw *ddraw;
7416 D3DVERTEX *quad;
7417 IDirect3D *d3d;
7418 ULONG refcount;
7419 WORD *indices;
7420 BOOL is_warp;
7421 HWND window;
7422 HRESULT hr;
7423 void *ptr;
7425 window = create_window();
7426 ddraw = create_ddraw();
7427 ok(!!ddraw, "Failed to create a ddraw object.\n");
7428 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7430 skip("Failed to create a 3D device, skipping test.\n");
7431 IDirectDraw_Release(ddraw);
7432 DestroyWindow(window);
7433 return;
7435 is_warp = ddraw_is_warp(ddraw);
7437 quad = malloc(vertex_count * sizeof(*quad));
7438 indices = malloc(indices_count * sizeof(*indices));
7439 for (i = 0, y = 0; y < vertices_side; ++y)
7441 for (x = 0; x < vertices_side; ++x)
7443 quad[i].x = x * 2.0f / (vertices_side - 1) - 1.0f;
7444 quad[i].y = y * 2.0f / (vertices_side - 1) - 1.0f;
7445 quad[i].z = 1.0f;
7446 quad[i].nx = 0.0f;
7447 quad[i].ny = 0.0f;
7448 quad[i].nz = -1.0f;
7449 quad[i].tu = 0.0f;
7450 quad[i++].tv = 0.0f;
7453 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
7455 for (x = 0; x < (vertices_side - 1); ++x)
7457 indices[i++] = y * vertices_side + x + 1;
7458 indices[i++] = y * vertices_side + x;
7459 indices[i++] = (y + 1) * vertices_side + x;
7460 indices[i++] = y * vertices_side + x + 1;
7461 indices[i++] = (y + 1) * vertices_side + x;
7462 indices[i++] = (y + 1) * vertices_side + x + 1;
7466 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
7467 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7469 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
7470 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7472 viewport = create_viewport(device, 0, 0, 640, 480);
7473 background_material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
7474 viewport_set_background(device, viewport, background_material);
7476 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7477 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7479 hr = IDirect3DDevice_CreateMatrix(device, &world_handle);
7480 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7481 hr = IDirect3DDevice_SetMatrix(device, world_handle, &mat);
7482 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7483 hr = IDirect3DDevice_CreateMatrix(device, &view_handle);
7484 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7485 hr = IDirect3DDevice_SetMatrix(device, view_handle, &mat);
7486 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7487 hr = IDirect3DDevice_CreateMatrix(device, &proj_handle);
7488 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7489 hr = IDirect3DDevice_SetMatrix(device, proj_handle, &mat);
7490 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7493 hr = IDirect3D_CreateLight(d3d, &light, NULL);
7494 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7495 hr = IDirect3DViewport_AddLight(viewport, light);
7496 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7498 memset(&exec_desc, 0, sizeof(exec_desc));
7499 exec_desc.dwSize = sizeof(exec_desc);
7500 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
7501 exec_desc.dwBufferSize = 10240;
7502 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
7504 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
7505 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7507 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7509 tests[i].light->dwFlags = D3DLIGHT_ACTIVE;
7510 material = create_specular_material(device, 1.0f, 1.0f, 1.0f, 1.0f, tests[i].specular_power);
7511 hr = IDirect3DMaterial_GetHandle(material, device, &mat_handle);
7512 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7514 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)tests[i].light);
7515 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7517 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7518 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7520 hr = IDirect3DDevice_BeginScene(device);
7521 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7523 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
7524 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7526 memcpy(exec_desc.lpData, quad, sizeof(*quad) * vertex_count);
7527 ptr = ((BYTE *)exec_desc.lpData) + sizeof(*quad) * vertex_count;
7529 emit_set_ls(&ptr, D3DLIGHTSTATE_MATERIAL, mat_handle);
7530 emit_set_ts(&ptr, D3DTRANSFORMSTATE_WORLD, world_handle);
7531 emit_set_ts(&ptr, D3DTRANSFORMSTATE_VIEW, view_handle);
7532 emit_set_ts(&ptr, D3DTRANSFORMSTATE_PROJECTION, proj_handle);
7533 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, FALSE);
7534 emit_set_rs(&ptr, D3DRENDERSTATE_SPECULARENABLE, TRUE);
7536 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, vertex_count);
7537 emit_tri_indices(&ptr, indices, indices_count / 3);
7538 emit_end(&ptr);
7539 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
7540 ok(inst_length <= exec_desc.dwBufferSize, "Execute buffer overflow, size %u.\n", inst_length);
7541 inst_length -= sizeof(*quad) * vertex_count;
7543 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
7544 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7546 set_execute_data(execute_buffer, vertex_count, sizeof(*quad) * vertex_count, inst_length);
7547 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
7548 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7550 hr = IDirect3DDevice_EndScene(device);
7551 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7553 for (j = 0; j < tests[i].expected_count; ++j)
7555 colour = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
7556 ok(compare_color(colour, tests[i].expected[j].colour, 1)
7557 || broken(is_warp && compare_color(colour, 0x00ff0000, 1)),
7558 "Expected colour 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
7559 tests[i].expected[j].colour, tests[i].expected[j].x,
7560 tests[i].expected[j].y, colour, i);
7562 destroy_material(material);
7565 IDirect3DExecuteBuffer_Release(execute_buffer);
7566 IDirect3DDevice_DeleteMatrix(device, world_handle);
7567 IDirect3DDevice_DeleteMatrix(device, view_handle);
7568 IDirect3DDevice_DeleteMatrix(device, proj_handle);
7570 hr = IDirect3DViewport_DeleteLight(viewport, light);
7571 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
7572 IDirect3DLight_Release(light);
7573 destroy_material(background_material);
7574 destroy_viewport(device, viewport);
7575 IDirectDrawSurface_Release(rt);
7576 refcount = IDirect3DDevice_Release(device);
7577 ok(!refcount, "Device has %lu references left.\n", refcount);
7578 IDirect3D_Release(d3d);
7579 refcount = IDirectDraw_Release(ddraw);
7580 ok(!refcount, "Ddraw object has %lu references left.\n", refcount);
7581 DestroyWindow(window);
7582 free(indices);
7583 free(quad);
7586 static void test_palette_gdi(void)
7588 IDirectDrawSurface *surface, *primary;
7589 DDSURFACEDESC surface_desc;
7590 unsigned int color, i;
7591 IDirectDraw *ddraw;
7592 IDirectDrawPalette *palette, *palette2;
7593 ULONG refcount;
7594 HWND window;
7595 HRESULT hr;
7596 PALETTEENTRY palette_entries[256];
7597 HDC dc;
7598 DDBLTFX fx;
7599 RECT r;
7601 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
7602 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
7603 * not the point of this test. */
7604 static const RGBQUAD expected1[] =
7606 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
7607 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
7609 static const RGBQUAD expected2[] =
7611 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
7612 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
7614 static const RGBQUAD expected3[] =
7616 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
7617 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
7619 HPALETTE ddraw_palette_handle;
7620 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
7621 RGBQUAD rgbquad[255];
7622 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
7624 window = create_window();
7625 ddraw = create_ddraw();
7626 ok(!!ddraw, "Failed to create a ddraw object.\n");
7627 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7628 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
7630 memset(&surface_desc, 0, sizeof(surface_desc));
7631 surface_desc.dwSize = sizeof(surface_desc);
7632 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7633 surface_desc.dwWidth = 16;
7634 surface_desc.dwHeight = 16;
7635 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7636 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7637 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7638 surface_desc.ddpfPixelFormat.dwRGBBitCount = 8;
7639 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7640 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
7642 /* Avoid colors from the Windows default palette. */
7643 memset(palette_entries, 0, sizeof(palette_entries));
7644 palette_entries[1].peRed = 0x01;
7645 palette_entries[2].peGreen = 0x02;
7646 palette_entries[3].peBlue = 0x03;
7647 palette_entries[4].peRed = 0x13;
7648 palette_entries[4].peGreen = 0x14;
7649 palette_entries[4].peBlue = 0x15;
7650 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7651 palette_entries, &palette, NULL);
7652 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
7654 /* If there is no palette assigned and the display mode is not 8 bpp, some
7655 * drivers refuse to create a DC while others allow it. If a DC is created,
7656 * the DIB color table is uninitialized and contains random colors. No error
7657 * is generated when trying to read pixels and random garbage is returned.
7659 * The most likely explanation is that if the driver creates a DC, it (or
7660 * the higher-level runtime) uses GetSystemPaletteEntries to find the
7661 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
7662 * contains uninitialized garbage. See comments below for the P8 case. */
7664 hr = IDirectDrawSurface_SetPalette(surface, palette);
7665 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
7666 hr = IDirectDrawSurface_GetDC(surface, &dc);
7667 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
7668 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
7669 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
7670 "Got unexpected palette %p, expected %p.\n",
7671 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
7673 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
7674 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
7675 for (i = 0; i < ARRAY_SIZE(expected1); i++)
7677 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
7678 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7679 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7680 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
7682 for (; i < ARRAY_SIZE(rgbquad); i++)
7684 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7685 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7686 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7689 /* Update the palette while the DC is in use. This does not modify the DC. */
7690 palette_entries[4].peRed = 0x23;
7691 palette_entries[4].peGreen = 0x24;
7692 palette_entries[4].peBlue = 0x25;
7693 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
7694 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#lx.\n", hr);
7696 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
7697 ok(i == 1, "Expected count 1, got %u.\n", i);
7698 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
7699 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7700 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
7701 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
7703 /* Neither does re-setting the palette. */
7704 hr = IDirectDrawSurface_SetPalette(surface, NULL);
7705 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
7706 hr = IDirectDrawSurface_SetPalette(surface, palette);
7707 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
7709 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
7710 ok(i == 1, "Expected count 1, got %u.\n", i);
7711 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
7712 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7713 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
7714 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
7716 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7717 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
7719 /* Refresh the DC. This updates the palette. */
7720 hr = IDirectDrawSurface_GetDC(surface, &dc);
7721 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
7722 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
7723 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
7724 for (i = 0; i < ARRAY_SIZE(expected2); i++)
7726 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7727 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7728 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7729 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7731 for (; i < ARRAY_SIZE(rgbquad); i++)
7733 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7734 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7735 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7737 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7738 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
7740 refcount = IDirectDrawSurface_Release(surface);
7741 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7743 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
7744 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
7745 if (FAILED(IDirectDraw_SetDisplayMode(ddraw, 640, 480, 8)))
7747 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7748 IDirectDrawPalette_Release(palette);
7749 IDirectDraw_Release(ddraw);
7750 DestroyWindow(window);
7751 return;
7753 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
7755 memset(&surface_desc, 0, sizeof(surface_desc));
7756 surface_desc.dwSize = sizeof(surface_desc);
7757 surface_desc.dwFlags = DDSD_CAPS;
7758 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7759 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
7760 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
7762 memset(&fx, 0, sizeof(fx));
7763 fx.dwSize = sizeof(fx);
7764 fx.dwFillColor = 3;
7765 SetRect(&r, 0, 0, 319, 479);
7766 hr = IDirectDrawSurface_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7767 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#lx.\n", hr);
7768 SetRect(&r, 320, 0, 639, 479);
7769 fx.dwFillColor = 4;
7770 hr = IDirectDrawSurface_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7771 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#lx.\n", hr);
7773 hr = IDirectDrawSurface_SetPalette(primary, palette);
7774 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
7775 hr = IDirectDrawSurface_GetDC(primary, &dc);
7776 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
7778 color = GetPixel(dc, 160, 240);
7779 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
7780 color = GetPixel(dc, 480, 240);
7781 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
7783 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
7784 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
7785 "Got unexpected palette %p, expected %p.\n",
7786 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
7787 SelectPalette(dc, ddraw_palette_handle, FALSE);
7789 /* The primary uses the system palette. In exclusive mode, the system palette matches
7790 * the ddraw palette attached to the primary, so the result is what you would expect
7791 * from a regular surface. Tests for the interaction between the ddraw palette and
7792 * the system palette are not included pending an application that depends on this.
7793 * The relation between those causes problems on Windows Vista and newer for games
7794 * like Age of Empires or StarCraft. Don't emulate it without a real need. */
7795 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
7796 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
7797 for (i = 0; i < ARRAY_SIZE(expected2); i++)
7799 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7800 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7801 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7802 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7804 for (; i < ARRAY_SIZE(rgbquad); i++)
7806 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7807 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7808 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7810 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
7811 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
7813 memset(&surface_desc, 0, sizeof(surface_desc));
7814 surface_desc.dwSize = sizeof(surface_desc);
7815 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7816 surface_desc.dwWidth = 16;
7817 surface_desc.dwHeight = 16;
7818 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7819 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7820 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
7822 /* Here the offscreen surface appears to use the primary's palette,
7823 * but in all likelihood it is actually the system palette. */
7824 hr = IDirectDrawSurface_GetDC(surface, &dc);
7825 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
7826 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
7827 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
7828 for (i = 0; i < ARRAY_SIZE(expected2); i++)
7830 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7831 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7832 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7833 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7835 for (; i < ARRAY_SIZE(rgbquad); i++)
7837 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7838 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7839 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7841 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7842 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
7844 /* On real hardware a change to the primary surface's palette applies immediately,
7845 * even on device contexts from offscreen surfaces that do not have their own
7846 * palette. On the testbot VMs this is not the case. Don't test this until we
7847 * know of an application that depends on this. */
7849 memset(palette_entries, 0, sizeof(palette_entries));
7850 palette_entries[1].peBlue = 0x40;
7851 palette_entries[2].peRed = 0x40;
7852 palette_entries[3].peGreen = 0x40;
7853 palette_entries[4].peRed = 0x12;
7854 palette_entries[4].peGreen = 0x34;
7855 palette_entries[4].peBlue = 0x56;
7856 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7857 palette_entries, &palette2, NULL);
7858 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
7859 hr = IDirectDrawSurface_SetPalette(surface, palette2);
7860 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
7862 /* A palette assigned to the offscreen surface overrides the primary / system
7863 * palette. */
7864 hr = IDirectDrawSurface_GetDC(surface, &dc);
7865 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
7866 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
7867 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
7868 for (i = 0; i < ARRAY_SIZE(expected3); i++)
7870 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
7871 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7872 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7873 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
7875 for (; i < ARRAY_SIZE(rgbquad); i++)
7877 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7878 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7879 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7881 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
7882 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
7884 refcount = IDirectDrawSurface_Release(surface);
7885 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7887 /* The Windows 8 testbot keeps extra references to the primary and
7888 * backbuffer while in 8 bpp mode. */
7889 hr = IDirectDraw_RestoreDisplayMode(ddraw);
7890 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#lx.\n", hr);
7892 refcount = IDirectDrawSurface_Release(primary);
7893 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7894 refcount = IDirectDrawPalette_Release(palette2);
7895 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7896 refcount = IDirectDrawPalette_Release(palette);
7897 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7898 refcount = IDirectDraw_Release(ddraw);
7899 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7900 DestroyWindow(window);
7903 static void test_palette_alpha(void)
7905 IDirectDrawSurface *surface;
7906 DDSURFACEDESC surface_desc;
7907 IDirectDraw *ddraw;
7908 IDirectDrawPalette *palette;
7909 ULONG refcount;
7910 HWND window;
7911 HRESULT hr;
7912 PALETTEENTRY palette_entries[256];
7913 unsigned int i;
7914 static const struct
7916 DWORD caps, flags;
7917 BOOL attach_allowed;
7918 const char *name;
7920 test_data[] =
7922 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
7923 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
7924 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
7927 window = create_window();
7928 ddraw = create_ddraw();
7929 ok(!!ddraw, "Failed to create a ddraw object.\n");
7930 if (FAILED(IDirectDraw_SetDisplayMode(ddraw, 640, 480, 8)))
7932 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7933 IDirectDraw_Release(ddraw);
7934 DestroyWindow(window);
7935 return;
7937 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7938 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
7940 memset(palette_entries, 0, sizeof(palette_entries));
7941 palette_entries[1].peFlags = 0x42;
7942 palette_entries[2].peFlags = 0xff;
7943 palette_entries[3].peFlags = 0x80;
7944 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
7945 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
7947 memset(palette_entries, 0x66, sizeof(palette_entries));
7948 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
7949 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#lx.\n", hr);
7950 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7951 palette_entries[0].peFlags);
7952 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7953 palette_entries[1].peFlags);
7954 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
7955 palette_entries[2].peFlags);
7956 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
7957 palette_entries[3].peFlags);
7959 IDirectDrawPalette_Release(palette);
7961 memset(palette_entries, 0, sizeof(palette_entries));
7962 palette_entries[1].peFlags = 0x42;
7963 palette_entries[1].peRed = 0xff;
7964 palette_entries[2].peFlags = 0xff;
7965 palette_entries[3].peFlags = 0x80;
7966 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
7967 palette_entries, &palette, NULL);
7968 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
7970 memset(palette_entries, 0x66, sizeof(palette_entries));
7971 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
7972 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#lx.\n", hr);
7973 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7974 palette_entries[0].peFlags);
7975 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7976 palette_entries[1].peFlags);
7977 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
7978 palette_entries[2].peFlags);
7979 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
7980 palette_entries[3].peFlags);
7982 for (i = 0; i < ARRAY_SIZE(test_data); i++)
7984 memset(&surface_desc, 0, sizeof(surface_desc));
7985 surface_desc.dwSize = sizeof(surface_desc);
7986 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
7987 surface_desc.dwWidth = 128;
7988 surface_desc.dwHeight = 128;
7989 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
7990 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7991 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#lx.\n", test_data[i].name, hr);
7993 hr = IDirectDrawSurface_SetPalette(surface, palette);
7994 if (test_data[i].attach_allowed)
7995 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#lx.\n", test_data[i].name, hr);
7996 else
7997 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#lx, %s surface.\n", hr, test_data[i].name);
7999 if (SUCCEEDED(hr))
8001 HDC dc;
8002 RGBQUAD rgbquad;
8003 UINT retval;
8005 hr = IDirectDrawSurface_GetDC(surface, &dc);
8006 ok(SUCCEEDED(hr) || broken(hr == DDERR_CANTCREATEDC) /* Win2k testbot */,
8007 "Failed to get DC, hr %#lx, %s surface.\n", hr, test_data[i].name);
8008 if (SUCCEEDED(hr))
8010 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
8011 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
8012 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
8013 rgbquad.rgbRed, test_data[i].name);
8014 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
8015 rgbquad.rgbGreen, test_data[i].name);
8016 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
8017 rgbquad.rgbBlue, test_data[i].name);
8018 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
8019 rgbquad.rgbReserved, test_data[i].name);
8020 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8021 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
8024 IDirectDrawSurface_Release(surface);
8027 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
8028 memset(&surface_desc, 0, sizeof(surface_desc));
8029 surface_desc.dwSize = sizeof(surface_desc);
8030 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8031 surface_desc.dwWidth = 128;
8032 surface_desc.dwHeight = 128;
8033 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8034 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
8035 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
8036 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
8037 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
8038 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
8039 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
8040 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8041 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8042 hr = IDirectDrawSurface_SetPalette(surface, palette);
8043 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#lx.\n", hr);
8044 IDirectDrawSurface_Release(surface);
8046 /* The Windows 8 testbot keeps extra references to the primary
8047 * while in 8 bpp mode. */
8048 hr = IDirectDraw_RestoreDisplayMode(ddraw);
8049 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#lx.\n", hr);
8051 refcount = IDirectDrawPalette_Release(palette);
8052 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8053 refcount = IDirectDraw_Release(ddraw);
8054 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8055 DestroyWindow(window);
8058 static void test_lost_device(void)
8060 IDirectDrawSurface *surface, *back_buffer, *back_buffer2, *ds;
8061 IDirectDrawSurface *sysmem_surface, *vidmem_surface;
8062 DDSURFACEDESC surface_desc;
8063 HWND window1, window2;
8064 IDirectDraw *ddraw;
8065 ULONG refcount;
8066 DDSCAPS caps;
8067 HRESULT hr;
8068 BOOL ret;
8070 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8071 0, 0, 640, 480, 0, 0, 0, 0);
8072 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8073 0, 0, 640, 480, 0, 0, 0, 0);
8074 ddraw = create_ddraw();
8075 ok(!!ddraw, "Failed to create a ddraw object.\n");
8076 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8077 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8079 memset(&surface_desc, 0, sizeof(surface_desc));
8080 surface_desc.dwSize = sizeof(surface_desc);
8081 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8082 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8083 surface_desc.dwBackBufferCount = 1;
8084 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8085 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8087 memset(&surface_desc, 0, sizeof(surface_desc));
8088 surface_desc.dwSize = sizeof(surface_desc);
8089 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8090 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
8091 surface_desc.dwWidth = 100;
8092 surface_desc.dwHeight = 100;
8093 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
8094 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8096 memset(&surface_desc, 0, sizeof(surface_desc));
8097 surface_desc.dwSize = sizeof(surface_desc);
8098 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8099 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
8100 surface_desc.dwWidth = 64;
8101 surface_desc.dwHeight = 64;
8102 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
8103 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
8104 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
8105 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
8106 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
8107 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
8108 if (FAILED(IDirectDraw_CreateSurface(ddraw, &surface_desc, &vidmem_surface, NULL)))
8110 skip("Failed to create video memory surface, skipping related tests.\n");
8111 vidmem_surface = NULL;
8114 hr = IDirectDrawSurface_IsLost(surface);
8115 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8116 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8117 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8118 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8119 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8120 if (vidmem_surface)
8122 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8123 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8126 ret = SetForegroundWindow(GetDesktopWindow());
8127 ok(ret, "Failed to set foreground window.\n");
8128 hr = IDirectDrawSurface_IsLost(surface);
8129 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8130 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8131 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8132 hr = IDirectDrawSurface_Restore(surface);
8133 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
8134 hr = IDirectDrawSurface_IsLost(surface);
8135 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8136 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8137 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8138 hr = IDirectDrawSurface_Restore(sysmem_surface);
8139 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8140 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8141 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8142 if (vidmem_surface)
8144 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8145 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8146 hr = IDirectDrawSurface_Restore(vidmem_surface);
8147 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
8148 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8149 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8152 ret = SetForegroundWindow(window1);
8153 ok(ret, "Failed to set foreground window.\n");
8154 hr = IDirectDrawSurface_IsLost(surface);
8155 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8156 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8157 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8158 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8159 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8160 if (vidmem_surface)
8162 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8163 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8166 hr = restore_surfaces(ddraw);
8167 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8168 hr = IDirectDrawSurface_IsLost(surface);
8169 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8170 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8171 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8172 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8173 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8174 if (vidmem_surface)
8176 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8177 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8180 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8181 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8182 hr = IDirectDrawSurface_IsLost(surface);
8183 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8184 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8185 ok(hr == DDERR_NOEXCLUSIVEMODE || broken(ddraw_is_warp(ddraw) && hr == DDERR_SURFACELOST),
8186 "Got unexpected hr %#lx.\n", hr);
8187 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8188 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8189 if (vidmem_surface)
8191 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8192 ok(hr == DD_OK || broken(ddraw_is_warp(ddraw) && hr == DDERR_SURFACELOST), "Got unexpected hr %#lx.\n", hr);
8195 /* Trying to restore the primary will crash, probably because flippable
8196 * surfaces can't exist in DDSCL_NORMAL. */
8197 IDirectDrawSurface_Release(surface);
8198 memset(&surface_desc, 0, sizeof(surface_desc));
8199 surface_desc.dwSize = sizeof(surface_desc);
8200 surface_desc.dwFlags = DDSD_CAPS;
8201 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8202 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8203 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8204 hr = restore_surfaces(ddraw);
8205 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8207 hr = IDirectDrawSurface_IsLost(surface);
8208 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8210 ret = SetForegroundWindow(GetDesktopWindow());
8211 ok(ret, "Failed to set foreground window.\n");
8212 hr = IDirectDrawSurface_IsLost(surface);
8213 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8214 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8215 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8216 if (vidmem_surface)
8218 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8219 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8222 ret = SetForegroundWindow(window1);
8223 ok(ret, "Failed to set foreground window.\n");
8224 hr = IDirectDrawSurface_IsLost(surface);
8225 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8226 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8227 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8228 if (vidmem_surface)
8230 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8231 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8234 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8235 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8236 hr = IDirectDrawSurface_IsLost(surface);
8237 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8238 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8239 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8240 if (vidmem_surface)
8242 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8243 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8246 hr = restore_surfaces(ddraw);
8247 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8248 hr = IDirectDrawSurface_IsLost(surface);
8249 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8250 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8251 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8252 if (vidmem_surface)
8254 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8255 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8258 IDirectDrawSurface_Release(surface);
8259 memset(&surface_desc, 0, sizeof(surface_desc));
8260 surface_desc.dwSize = sizeof(surface_desc);
8261 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8262 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8263 surface_desc.dwBackBufferCount = 2;
8264 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8265 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8267 ds = NULL;
8268 memset(&surface_desc, 0, sizeof(surface_desc));
8269 surface_desc.dwSize = sizeof(surface_desc);
8270 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
8271 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8273 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
8274 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
8275 surface_desc.dwZBufferBitDepth = 16;
8276 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL);
8277 if (FAILED(hr))
8279 skip("Could not create Z buffer, skipping Z buffer restore test.\n");
8281 else
8283 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
8284 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8287 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8288 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8289 hr = IDirectDrawSurface_IsLost(surface);
8290 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8291 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8292 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8293 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8294 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8295 if (vidmem_surface)
8297 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8298 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8301 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8302 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8303 hr = IDirectDrawSurface_IsLost(surface);
8304 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8305 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8306 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
8307 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8308 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8309 if (vidmem_surface)
8311 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8312 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8315 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8316 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8317 hr = IDirectDrawSurface_IsLost(surface);
8318 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8319 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8320 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
8321 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8322 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8323 if (vidmem_surface)
8325 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8326 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8329 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
8330 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8331 hr = IDirectDrawSurface_IsLost(surface);
8332 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8333 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8334 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
8335 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8336 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8337 if (vidmem_surface)
8339 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8340 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8343 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8344 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8345 hr = IDirectDrawSurface_IsLost(surface);
8346 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8347 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8348 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
8349 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8350 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8351 if (vidmem_surface)
8353 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8354 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8357 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8358 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8359 hr = IDirectDrawSurface_IsLost(surface);
8360 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8361 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8362 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8363 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8364 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8365 if (vidmem_surface)
8367 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8368 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8371 memset(&caps, 0, sizeof(caps));
8372 caps.dwCaps = DDSCAPS_FLIP;
8374 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &back_buffer);
8375 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8376 ok(back_buffer != surface, "Got the same surface.\n");
8377 hr = IDirectDrawSurface_Restore(surface);
8378 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8379 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &back_buffer);
8380 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8381 hr = IDirectDrawSurface_IsLost(back_buffer);
8382 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8383 IDirectDrawSurface_Release(back_buffer);
8385 hr = IDirectDrawSurface_GetAttachedSurface(back_buffer, &caps, &back_buffer2);
8386 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8387 ok(back_buffer2 != back_buffer, "Got the same surface.\n");
8388 ok(back_buffer2 != surface, "Got the same surface.\n");
8389 hr = IDirectDrawSurface_IsLost(back_buffer2);
8390 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8391 IDirectDrawSurface_Release(back_buffer2);
8393 if (ds)
8395 hr = IDirectDrawSurface_IsLost(ds);
8396 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8397 hr = IDirectDrawSurface_Restore(ds);
8398 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8399 hr = IDirectDrawSurface_IsLost(ds);
8400 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8401 IDirectDrawSurface_Release(ds);
8404 if (vidmem_surface)
8405 IDirectDrawSurface_Release(vidmem_surface);
8406 IDirectDrawSurface_Release(sysmem_surface);
8407 IDirectDrawSurface_Release(surface);
8408 refcount = IDirectDraw_Release(ddraw);
8409 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8410 DestroyWindow(window2);
8411 DestroyWindow(window1);
8414 static void test_surface_desc_lock(void)
8416 IDirectDrawSurface *surface;
8417 DDSURFACEDESC surface_desc;
8418 IDirectDraw *ddraw;
8419 ULONG refcount;
8420 HWND window;
8421 HRESULT hr;
8423 window = create_window();
8424 ddraw = create_ddraw();
8425 ok(!!ddraw, "Failed to create a ddraw object.\n");
8426 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8427 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
8429 memset(&surface_desc, 0, sizeof(surface_desc));
8430 surface_desc.dwSize = sizeof(surface_desc);
8431 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8432 surface_desc.dwWidth = 16;
8433 surface_desc.dwHeight = 16;
8434 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8435 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8436 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8438 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8439 surface_desc.dwSize = sizeof(surface_desc);
8440 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
8441 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
8442 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8444 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8445 surface_desc.dwSize = sizeof(surface_desc);
8446 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, 0, NULL);
8447 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
8448 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8449 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8450 surface_desc.dwSize = sizeof(surface_desc);
8451 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
8452 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
8453 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8454 hr = IDirectDrawSurface_Unlock(surface, NULL);
8455 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
8457 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8458 surface_desc.dwSize = sizeof(surface_desc);
8459 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
8460 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
8461 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8463 IDirectDrawSurface_Release(surface);
8464 refcount = IDirectDraw_Release(ddraw);
8465 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8466 DestroyWindow(window);
8469 static void test_texturemapblend(void)
8471 HRESULT hr;
8472 DDSURFACEDESC ddsd;
8473 D3DEXECUTEBUFFERDESC exec_desc;
8474 DDBLTFX fx;
8475 static RECT rect = {0, 0, 64, 128};
8476 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8477 DDCOLORKEY ckey;
8478 IDirectDrawSurface *surface, *rt;
8479 unsigned int inst_length, color;
8480 IDirect3DTexture *texture;
8481 D3DTEXTUREHANDLE texture_handle;
8482 HWND window;
8483 IDirectDraw *ddraw;
8484 IDirect3DDevice *device;
8485 IDirect3DMaterial *material;
8486 IDirect3DViewport *viewport;
8487 IDirect3DExecuteBuffer *execute_buffer;
8488 void *ptr;
8489 ULONG ref;
8491 static const D3DTLVERTEX test1_quads[] =
8493 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {0.0f}},
8494 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {1.0f}},
8495 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {0.0f}},
8496 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {1.0f}},
8497 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {0.0f}},
8498 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {1.0f}},
8499 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {0.0f}},
8500 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {1.0f}},
8502 test2_quads[] =
8504 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {0.0f}},
8505 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {1.0f}},
8506 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {0.0f}},
8507 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {1.0f}},
8508 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {0.0f}},
8509 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {1.0f}},
8510 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {0.0f}},
8511 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {1.0f}},
8514 window = create_window();
8515 ddraw = create_ddraw();
8516 ok(!!ddraw, "Failed to create a ddraw object.\n");
8517 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8519 skip("Failed to create a 3D device, skipping test.\n");
8520 DestroyWindow(window);
8521 IDirectDraw_Release(ddraw);
8522 return;
8525 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
8526 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
8528 material = create_diffuse_material(device, 0.0f, 0.0f, 0.0f, 1.0f);
8529 viewport = create_viewport(device, 0, 0, 640, 480);
8530 viewport_set_background(device, viewport, material);
8532 memset(&exec_desc, 0, sizeof(exec_desc));
8533 exec_desc.dwSize = sizeof(exec_desc);
8534 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
8535 exec_desc.dwBufferSize = 1024;
8536 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
8537 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
8538 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#lx.\n", hr);
8540 /* Test alpha with DDPF_ALPHAPIXELS texture - should be taken from texture alpha channel.
8542 * The vertex alpha is completely ignored in this case, so case 1 and 2 combined are not
8543 * a D3DTOP_MODULATE with texture alpha = 0xff in case 2 (no alpha in texture). */
8544 memset(&ddsd, 0, sizeof(ddsd));
8545 ddsd.dwSize = sizeof(ddsd);
8546 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
8547 ddsd.dwHeight = 128;
8548 ddsd.dwWidth = 128;
8549 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8550 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
8551 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
8552 ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
8553 ddsd.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
8554 ddsd.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
8555 ddsd.ddpfPixelFormat.dwBBitMask = 0x000000ff;
8556 ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
8557 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
8558 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8560 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
8561 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
8562 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
8563 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#lx.\n", hr);
8565 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8566 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
8568 memset(&fx, 0, sizeof(fx));
8569 fx.dwSize = sizeof(fx);
8570 fx.dwFillColor = 0xff0000ff;
8571 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8572 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
8573 fx.dwFillColor = 0x800000ff;
8574 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8575 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
8577 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
8578 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#lx.\n", hr);
8580 memcpy(exec_desc.lpData, test1_quads, sizeof(test1_quads));
8582 ptr = ((BYTE *)exec_desc.lpData) + sizeof(test1_quads);
8583 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
8584 emit_set_rs(&ptr, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
8585 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
8586 emit_set_rs(&ptr, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
8587 emit_set_rs(&ptr, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
8588 /* The history of D3DRENDERSTATE_ALPHABLENDENABLE is quite a mess. In the
8589 * first D3D release there was a D3DRENDERSTATE_BLENDENABLE (enum value 27).
8590 * D3D5 introduced a new and separate D3DRENDERSTATE_ALPHABLENDENABLE (42)
8591 * together with D3DRENDERSTATE_COLORKEYENABLE (41). The docs aren't all
8592 * that clear but they mention that D3DRENDERSTATE_BLENDENABLE overrides the
8593 * two new states.
8594 * Then D3D6 came and got rid of the new D3DRENDERSTATE_ALPHABLENDENABLE
8595 * state (42), renaming the older D3DRENDERSTATE_BLENDENABLE enum (27)
8596 * as D3DRENDERSTATE_ALPHABLENDENABLE.
8597 * There is a comment in the D3D6 docs which mentions that hardware
8598 * rasterizers always used D3DRENDERSTATE_BLENDENABLE to just toggle alpha
8599 * blending while prior to D3D5 software rasterizers toggled both color
8600 * keying and alpha blending according to it. What I gather is that, from
8601 * D3D6 onwards, D3DRENDERSTATE_ALPHABLENDENABLE always only toggles the
8602 * alpha blending state.
8603 * These tests seem to show that actual, current hardware follows the D3D6
8604 * behavior even when using the original D3D interfaces, for the HAL device
8605 * at least. */
8606 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
8607 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
8608 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
8610 /* SPECULARENABLE shouldn't matter in this test, but WARP begs to
8611 * differ. In the event that color keying is randomly on (see comments
8612 * in test_ck_default for reference), WARP will randomly discard
8613 * fragments based on something, even though texture and diffuse color
8614 * alpha components are non-zero. Setting SPECULARENABLE to FALSE
8615 * prevents this in some cases - presumably WARP multiplies the
8616 * specular color "alpha" channel into the final result and then
8617 * alpha tests the result. Since the specular property normally does
8618 * not have an alpha component the actual specular color we set in
8619 * the vertex data above does not matter. Setting FOGENABLE = FALSE
8620 * does not help either (specular alpha can contain a per-vertex fog
8621 * factor. Doesn't seem to matter here). */
8622 emit_set_rs(&ptr, D3DRENDERSTATE_SPECULARENABLE, FALSE);
8624 emit_tquad(&ptr, 0);
8625 emit_tquad(&ptr, 4);
8626 emit_end(&ptr);
8628 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
8629 inst_length -= sizeof(test1_quads);
8630 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
8631 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#lx.\n", hr);
8632 set_execute_data(execute_buffer, 8, sizeof(test1_quads), inst_length);
8634 hr = IDirect3DDevice_BeginScene(device);
8635 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
8636 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
8637 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#lx.\n", hr);
8638 hr = IDirect3DDevice_EndScene(device);
8639 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
8641 /* The above SPECULARENABLE = FALSE on WARP matters here.*/
8642 color = get_surface_color(rt, 5, 5);
8643 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
8644 color = get_surface_color(rt, 400, 5);
8645 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
8646 color = get_surface_color(rt, 5, 245);
8647 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
8648 color = get_surface_color(rt, 400, 245);
8649 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
8651 IDirect3DTexture_Release(texture);
8652 ref = IDirectDrawSurface_Release(surface);
8653 ok(!ref, "Unexpected refcount %lu.\n", ref);
8655 /* Test alpha with texture that has no alpha channel - alpha should be taken from diffuse vertex color. */
8656 memset(&ddsd, 0, sizeof(ddsd));
8657 ddsd.dwSize = sizeof(ddsd);
8658 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
8659 ddsd.dwHeight = 128;
8660 ddsd.dwWidth = 128;
8661 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8662 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
8663 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
8664 ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
8665 ddsd.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
8666 ddsd.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
8667 ddsd.ddpfPixelFormat.dwBBitMask = 0x000000ff;
8669 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
8670 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8672 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
8673 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
8674 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
8675 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#lx.\n", hr);
8677 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8678 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
8680 fx.dwFillColor = 0xff0000ff;
8681 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8682 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
8683 fx.dwFillColor = 0x800000ff;
8684 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8685 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
8687 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
8688 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#lx.\n", hr);
8690 ptr = ((BYTE *)exec_desc.lpData) + sizeof(test1_quads);
8691 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
8692 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
8694 emit_tquad(&ptr, 0);
8695 emit_tquad(&ptr, 4);
8696 emit_end(&ptr);
8698 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
8699 inst_length -= sizeof(test1_quads);
8700 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
8701 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#lx.\n", hr);
8702 set_execute_data(execute_buffer, 8, sizeof(test1_quads), inst_length);
8704 hr = IDirect3DDevice_BeginScene(device);
8705 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
8706 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
8707 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#lx.\n", hr);
8708 hr = IDirect3DDevice_EndScene(device);
8709 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
8711 /* Despite our best efforts at not making color keying randomly triggering, those
8712 * four broken() results occur every now and then on WARP. Presumably the non-
8713 * existent alpha channel sometimes samples 0.0 instead of the expected 1.0. */
8714 color = get_surface_color(rt, 5, 5);
8715 ok(compare_color(color, 0x000000ff, 2)
8716 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x00000000, 2)),
8717 "Got unexpected color 0x%08x.\n", color);
8718 color = get_surface_color(rt, 400, 5);
8719 ok(compare_color(color, 0x000000ff, 2)
8720 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x00000000, 2)),
8721 "Got unexpected color 0x%08x.\n", color);
8722 color = get_surface_color(rt, 5, 245);
8723 ok(compare_color(color, 0x00000080, 2)
8724 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x00000000, 2)),
8725 "Got unexpected color 0x%08x.\n", color);
8726 color = get_surface_color(rt, 400, 245);
8727 ok(compare_color(color, 0x00000080, 2)
8728 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x00000000, 2)),
8729 "Got unexpected color 0x%08x.\n", color);
8731 IDirect3DTexture_Release(texture);
8732 ref = IDirectDrawSurface_Release(surface);
8733 ok(!ref, "Unexpected refcount %lu.\n", ref);
8735 /* Test RGB - should multiply color components from diffuse vertex color and texture. */
8736 memset(&ddsd, 0, sizeof(ddsd));
8737 ddsd.dwSize = sizeof(ddsd);
8738 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
8739 ddsd.dwHeight = 128;
8740 ddsd.dwWidth = 128;
8741 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8742 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
8743 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
8744 ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
8745 ddsd.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
8746 ddsd.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
8747 ddsd.ddpfPixelFormat.dwBBitMask = 0x000000ff;
8748 ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
8749 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
8750 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8752 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
8753 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
8754 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
8755 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#lx.\n", hr);
8757 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8758 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
8760 fx.dwFillColor = 0x00ffffff;
8761 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8762 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
8763 fx.dwFillColor = 0x00ffff80;
8764 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8765 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
8767 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
8768 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#lx.\n", hr);
8770 memcpy(exec_desc.lpData, test2_quads, sizeof(test2_quads));
8772 ptr = ((BYTE *)exec_desc.lpData) + sizeof(test2_quads);
8773 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
8774 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
8775 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
8777 emit_tquad(&ptr, 0);
8778 emit_tquad(&ptr, 4);
8779 emit_end(&ptr);
8781 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
8782 inst_length -= sizeof(test2_quads);
8783 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
8784 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#lx.\n", hr);
8785 set_execute_data(execute_buffer, 8, sizeof(test2_quads), inst_length);
8787 hr = IDirect3DDevice_BeginScene(device);
8788 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
8789 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
8790 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#lx.\n", hr);
8791 hr = IDirect3DDevice_EndScene(device);
8792 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
8794 /* WARP (Win8 testbot) emulates color keying with the alpha channel like Wine does,
8795 * but even applies it when there's no color key assigned. The surface alpha is zero
8796 * here, so nothing gets drawn.
8798 * The ddraw2 version of this test draws these quads with color keying off due to
8799 * different defaults in ddraw1 and ddraw2. */
8800 color = get_surface_color(rt, 5, 5);
8801 ok(compare_color(color, 0x00ff0040, 2) || broken(compare_color(color, 0x00000000, 1)),
8802 "Got unexpected color 0x%08x.\n", color);
8803 color = get_surface_color(rt, 400, 5);
8804 ok(compare_color(color, 0x00ff0080, 2) || broken(compare_color(color, 0x00000000, 1)),
8805 "Got unexpected color 0x%08x.\n", color);
8806 color = get_surface_color(rt, 5, 245);
8807 ok(compare_color(color, 0x00800080, 2) || broken(compare_color(color, 0x00000000, 1)),
8808 "Got unexpected color 0x%08x.\n", color);
8809 color = get_surface_color(rt, 400, 245);
8810 ok(compare_color(color, 0x008000ff, 2) || broken(compare_color(color, 0x00000000, 1)),
8811 "Got unexpected color 0x%08x.\n", color);
8813 IDirect3DTexture_Release(texture);
8814 ref = IDirectDrawSurface_Release(surface);
8815 ok(!ref, "Unexpected refcount %lu.\n", ref);
8817 /* Test alpha again, now with color keyed texture (colorkey emulation in wine can interfere). */
8818 memset(&ddsd, 0, sizeof(ddsd));
8819 ddsd.dwSize = sizeof(ddsd);
8820 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
8821 ddsd.dwHeight = 128;
8822 ddsd.dwWidth = 128;
8823 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8824 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
8825 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
8826 ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
8827 ddsd.ddpfPixelFormat.dwRBitMask = 0xf800;
8828 ddsd.ddpfPixelFormat.dwGBitMask = 0x07e0;
8829 ddsd.ddpfPixelFormat.dwBBitMask = 0x001f;
8831 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
8832 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8834 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
8835 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
8836 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
8837 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#lx.\n", hr);
8839 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8840 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
8842 fx.dwFillColor = 0xf800;
8843 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8844 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
8845 fx.dwFillColor = 0x001f;
8846 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8847 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
8849 ckey.dwColorSpaceLowValue = 0x001f;
8850 ckey.dwColorSpaceHighValue = 0x001f;
8851 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
8852 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
8854 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
8855 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#lx.\n", hr);
8857 memcpy(exec_desc.lpData, test1_quads, sizeof(test1_quads));
8859 ptr = ((BYTE *)exec_desc.lpData) + sizeof(test1_quads);
8860 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
8861 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
8862 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
8863 /* D3DRENDERSTATE_COLORKEYENABLE is supposed to be on by default on version
8864 * 1 devices, but for some reason it randomly defaults to FALSE on the W8
8865 * testbot. This is either the fault of Windows 8 or the WARP driver.
8866 * Also D3DRENDERSTATE_COLORKEYENABLE was introduced in D3D 5 aka version 2
8867 * devices only, which might imply this doesn't actually do anything on
8868 * WARP. */
8869 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
8871 emit_tquad(&ptr, 0);
8872 emit_tquad(&ptr, 4);
8873 emit_end(&ptr);
8875 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
8876 inst_length -= sizeof(test1_quads);
8877 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
8878 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#lx.\n", hr);
8879 set_execute_data(execute_buffer, 8, sizeof(test1_quads), inst_length);
8881 hr = IDirect3DDevice_BeginScene(device);
8882 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
8883 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
8884 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#lx.\n", hr);
8885 hr = IDirect3DDevice_EndScene(device);
8886 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
8888 /* Allow broken WARP results (colorkey disabled). */
8889 color = get_surface_color(rt, 5, 5);
8890 ok(compare_color(color, 0x00000000, 2) || broken(compare_color(color, 0x000000ff, 2)),
8891 "Got unexpected color 0x%08x.\n", color);
8892 color = get_surface_color(rt, 400, 5);
8893 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
8894 color = get_surface_color(rt, 5, 245);
8895 ok(compare_color(color, 0x00000000, 2) || broken(compare_color(color, 0x00000080, 2)),
8896 "Got unexpected color 0x%08x.\n", color);
8897 color = get_surface_color(rt, 400, 245);
8898 ok(compare_color(color, 0x00800000, 2), "Got unexpected color 0x%08x.\n", color);
8900 IDirect3DTexture_Release(texture);
8901 ref = IDirectDrawSurface_Release(surface);
8902 ok(!ref, "Unexpected refcount %lu.\n", ref);
8904 ref = IDirect3DExecuteBuffer_Release(execute_buffer);
8905 ok(ref == 0, "Execute buffer not properly released, refcount %lu.\n", ref);
8906 destroy_viewport(device, viewport);
8907 ref = IDirect3DMaterial_Release(material);
8908 ok(ref == 0, "Material not properly released, refcount %lu.\n", ref);
8909 IDirectDrawSurface_Release(rt);
8910 IDirect3DDevice_Release(device);
8911 ref = IDirectDraw_Release(ddraw);
8912 ok(!ref, "Unexpected refcount %lu.\n", ref);
8913 DestroyWindow(window);
8916 static void test_viewport_clear_rect(void)
8918 HRESULT hr;
8919 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8920 static D3DRECT clear_rect2 = {{90}, {90}, {110}, {110}};
8921 IDirectDrawSurface *rt;
8922 unsigned int color;
8923 HWND window;
8924 IDirectDraw *ddraw;
8925 IDirect3DDevice *device;
8926 IDirect3DMaterial *red, *green;
8927 IDirect3DViewport *viewport, *viewport2;
8928 ULONG ref;
8930 window = create_window();
8931 ddraw = create_ddraw();
8932 ok(!!ddraw, "Failed to create a ddraw object.\n");
8933 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8935 skip("Failed to create a 3D device, skipping test.\n");
8936 DestroyWindow(window);
8937 IDirectDraw_Release(ddraw);
8938 return;
8941 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
8942 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
8944 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
8945 viewport = create_viewport(device, 0, 0, 640, 480);
8946 viewport_set_background(device, viewport, red);
8947 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8948 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
8950 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
8951 viewport2 = create_viewport(device, 100, 100, 20, 20);
8952 viewport_set_background(device, viewport2, green);
8953 hr = IDirect3DViewport_Clear(viewport2, 1, &clear_rect2, D3DCLEAR_TARGET);
8954 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
8956 color = get_surface_color(rt, 85, 85); /* Outside both. */
8957 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8958 color = get_surface_color(rt, 95, 95); /* Outside vp, inside rect. */
8959 /* AMD GPUs ignore the viewport dimensions and only care about the rectangle. */
8960 ok(compare_color(color, 0x00ff0000, 1) || broken(compare_color(color, 0x0000ff00, 1)),
8961 "Got unexpected color 0x%08x.\n", color);
8962 color = get_surface_color(rt, 105, 105); /* Inside both. */
8963 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
8964 color = get_surface_color(rt, 115, 115); /* Inside vp, outside rect. */
8965 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8966 color = get_surface_color(rt, 125, 125); /* Outside both. */
8967 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
8969 destroy_viewport(device, viewport2);
8970 destroy_material(green);
8971 destroy_viewport(device, viewport);
8972 destroy_material(red);
8973 IDirectDrawSurface_Release(rt);
8974 IDirect3DDevice_Release(device);
8975 ref = IDirectDraw_Release(ddraw);
8976 ok(!ref, "Unexpected refcount %lu.\n", ref);
8977 DestroyWindow(window);
8980 static void test_color_fill(void)
8982 HRESULT hr;
8983 IDirect3DDevice *device;
8984 IDirectDraw *ddraw;
8985 IDirectDrawSurface *surface, *surface2;
8986 DDSURFACEDESC surface_desc;
8987 unsigned int i, *color;
8988 ULONG refcount;
8989 HWND window;
8990 BOOL is_warp;
8991 DDBLTFX fx;
8992 RECT rect = {5, 5, 7, 7};
8993 DWORD num_fourcc_codes, *fourcc_codes;
8994 DDCAPS hal_caps;
8995 BOOL support_uyvy = FALSE, support_yuy2 = FALSE;
8996 static const struct
8998 DWORD caps;
8999 HRESULT colorfill_hr, depthfill_hr;
9000 BOOL rop_success;
9001 const char *name;
9002 unsigned int result;
9003 BOOL check_result;
9004 DDPIXELFORMAT format;
9006 tests[] =
9009 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
9010 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
9012 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9013 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9017 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
9018 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
9020 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9021 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9025 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
9026 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
9028 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9029 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9033 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
9034 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
9036 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9037 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9041 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY,
9042 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0xdeadbeef, TRUE,
9043 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9046 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
9047 * different afterwards. DX9+ GPUs set one of the two luminance values
9048 * in each block, but AMD and Nvidia GPUs disagree on which luminance
9049 * value they set. r200 (dx8) just sets the entire block to the clear
9050 * value. */
9051 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
9052 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
9054 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9055 {0}, {0}, {0}, {0}, {0}
9059 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
9060 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
9062 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9063 {0}, {0}, {0}, {0}, {0}
9067 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
9068 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
9070 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9071 {0}, {0}, {0}, {0}, {0}
9075 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
9076 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
9078 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9079 {0}, {0}, {0}, {0}, {0}
9083 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
9084 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
9086 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9087 {0}, {0}, {0}, {0}, {0}
9091 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
9092 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
9094 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9095 {0}, {0}, {0}, {0}, {0}
9099 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
9100 * surface works, presumably because it is handled by the runtime instead of
9101 * the driver. */
9102 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
9103 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
9105 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9106 {8}, {0}, {0}, {0}, {0}
9110 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
9111 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
9113 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9114 {8}, {0}, {0}, {0}, {0}
9118 static const struct
9120 DWORD rop;
9121 const char *name;
9122 HRESULT hr;
9124 rops[] =
9126 {SRCCOPY, "SRCCOPY", DD_OK},
9127 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
9128 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
9129 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
9130 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
9131 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
9132 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
9133 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
9134 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
9135 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
9136 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
9137 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
9138 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
9139 {BLACKNESS, "BLACKNESS", DD_OK},
9140 {WHITENESS, "WHITENESS", DD_OK},
9141 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
9144 window = create_window();
9145 ddraw = create_ddraw();
9146 ok(!!ddraw, "Failed to create a ddraw object.\n");
9147 is_warp = ddraw_is_warp(ddraw);
9148 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
9150 skip("Failed to create a 3D device, skipping test.\n");
9151 DestroyWindow(window);
9152 IDirectDraw_Release(ddraw);
9153 return;
9156 hr = IDirectDraw_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
9157 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
9158 fourcc_codes = calloc(num_fourcc_codes, sizeof(*fourcc_codes));
9159 if (!fourcc_codes)
9160 goto done;
9161 hr = IDirectDraw_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
9162 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
9163 for (i = 0; i < num_fourcc_codes; i++)
9165 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
9166 support_yuy2 = TRUE;
9167 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
9168 support_uyvy = TRUE;
9170 free(fourcc_codes);
9172 memset(&hal_caps, 0, sizeof(hal_caps));
9173 hal_caps.dwSize = sizeof(hal_caps);
9174 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
9175 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
9177 if ((!support_yuy2 && !support_uyvy) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9178 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
9180 for (i = 0; i < ARRAY_SIZE(tests); i++)
9182 DWORD expected_broken = tests[i].result;
9183 unsigned int mask = 0xffffffffu;
9185 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
9186 memset(&fx, 0, sizeof(fx));
9187 fx.dwSize = sizeof(fx);
9188 fx.dwFillColor = 0xdeadbeef;
9190 memset(&surface_desc, 0, sizeof(surface_desc));
9191 surface_desc.dwSize = sizeof(surface_desc);
9192 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9193 surface_desc.dwWidth = 64;
9194 surface_desc.dwHeight = 64;
9195 surface_desc.ddpfPixelFormat = tests[i].format;
9196 surface_desc.ddsCaps.dwCaps = tests[i].caps;
9198 if (tests[i].caps & DDSCAPS_TEXTURE)
9200 struct format_support_check check = {&tests[i].format, FALSE};
9201 hr = IDirect3DDevice_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
9202 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
9203 if (!check.supported)
9204 continue;
9207 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !support_yuy2)
9208 continue;
9209 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !support_uyvy)
9210 continue;
9211 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9212 continue;
9214 if (tests[i].caps & DDSCAPS_ZBUFFER)
9216 surface_desc.dwFlags &= ~DDSD_PIXELFORMAT;
9217 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
9218 surface_desc.dwZBufferBitDepth = get_device_z_depth(device);
9219 mask >>= (32 - surface_desc.dwZBufferBitDepth);
9220 /* Some drivers seem to convert depth values incorrectly or not at
9221 * all. Affects at least AMD PALM, 8.17.10.1247. */
9222 if (tests[i].caps & DDSCAPS_VIDEOMEMORY)
9224 DWORD expected;
9225 float f, g;
9227 expected = tests[i].result & mask;
9228 f = ceilf(logf(expected + 1.0f) / logf(2.0f));
9229 g = (f + 1.0f) / 2.0f;
9230 g -= (int)g;
9231 expected_broken = (expected / exp2f(f) - g) * 256;
9232 expected_broken *= 0x01010101;
9236 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9237 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx, surface %s.\n", hr, tests[i].name);
9239 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9240 todo_wine_if (tests[i].format.dwFourCC)
9241 ok(hr == tests[i].colorfill_hr, "Blt returned %#lx, expected %#lx, surface %s.\n",
9242 hr, tests[i].colorfill_hr, tests[i].name);
9244 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9245 todo_wine_if (tests[i].format.dwFourCC)
9246 ok(hr == tests[i].colorfill_hr, "Blt returned %#lx, expected %#lx, surface %s.\n",
9247 hr, tests[i].colorfill_hr, tests[i].name);
9249 if (SUCCEEDED(hr) && tests[i].check_result)
9251 memset(&surface_desc, 0, sizeof(surface_desc));
9252 surface_desc.dwSize = sizeof(surface_desc);
9253 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9254 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
9255 color = surface_desc.lpSurface;
9256 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
9257 *color, tests[i].result, tests[i].name);
9258 hr = IDirectDrawSurface_Unlock(surface, NULL);
9259 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
9262 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9263 ok(hr == tests[i].depthfill_hr, "Blt returned %#lx, expected %#lx, surface %s.\n",
9264 hr, tests[i].depthfill_hr, tests[i].name);
9265 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9266 ok(hr == tests[i].depthfill_hr, "Blt returned %#lx, expected %#lx, surface %s.\n",
9267 hr, tests[i].depthfill_hr, tests[i].name);
9269 if (SUCCEEDED(hr) && tests[i].check_result)
9271 memset(&surface_desc, 0, sizeof(surface_desc));
9272 surface_desc.dwSize = sizeof(surface_desc);
9273 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9274 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
9275 color = surface_desc.lpSurface;
9276 todo_wine_if(tests[i].caps & DDSCAPS_VIDEOMEMORY && surface_desc.dwZBufferBitDepth != 16)
9277 ok((*color & mask) == (tests[i].result & mask) || broken((*color & mask) == (expected_broken & mask))
9278 || broken(is_warp && (*color & mask) == (~0u & mask)) /* Windows 8+ testbot. */,
9279 "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
9280 *color & mask, tests[i].result & mask, tests[i].name);
9281 hr = IDirectDrawSurface_Unlock(surface, NULL);
9282 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
9285 fx.dwFillColor = 0xdeadbeef;
9286 fx.dwROP = BLACKNESS;
9287 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9288 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#lx, expected %s, surface %s.\n",
9289 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9290 ok(fx.dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08lx, surface %s\n",
9291 fx.dwFillColor, tests[i].name);
9293 if (SUCCEEDED(hr) && tests[i].check_result)
9295 memset(&surface_desc, 0, sizeof(surface_desc));
9296 surface_desc.dwSize = sizeof(surface_desc);
9297 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9298 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
9299 color = surface_desc.lpSurface;
9300 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
9301 *color, tests[i].name);
9302 hr = IDirectDrawSurface_Unlock(surface, NULL);
9303 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
9306 fx.dwROP = WHITENESS;
9307 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9308 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#lx, expected %s, surface %s.\n",
9309 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9310 ok(fx.dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08lx, surface %s\n",
9311 fx.dwFillColor, tests[i].name);
9313 if (SUCCEEDED(hr) && tests[i].check_result)
9315 memset(&surface_desc, 0, sizeof(surface_desc));
9316 surface_desc.dwSize = sizeof(surface_desc);
9317 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9318 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
9319 color = surface_desc.lpSurface;
9320 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
9321 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
9322 *color, tests[i].name);
9323 hr = IDirectDrawSurface_Unlock(surface, NULL);
9324 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
9327 IDirectDrawSurface_Release(surface);
9330 memset(&fx, 0, sizeof(fx));
9331 fx.dwSize = sizeof(fx);
9332 fx.dwFillColor = 0xdeadbeef;
9333 fx.dwROP = WHITENESS;
9335 memset(&surface_desc, 0, sizeof(surface_desc));
9336 surface_desc.dwSize = sizeof(surface_desc);
9337 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9338 surface_desc.dwWidth = 64;
9339 surface_desc.dwHeight = 64;
9340 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
9341 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
9342 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
9343 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
9344 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
9345 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
9346 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
9347 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9348 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9349 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
9350 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9352 /* No DDBLTFX. */
9353 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
9354 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9355 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
9356 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9358 /* Unused source rectangle. */
9359 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9360 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
9361 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9362 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
9364 /* Unused source surface. */
9365 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9366 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9367 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9368 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
9369 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9370 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9371 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9372 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
9374 /* Inverted destination or source rectangle. */
9375 SetRect(&rect, 5, 7, 7, 5);
9376 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9377 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
9378 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9379 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
9380 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9381 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9382 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9383 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9384 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9385 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
9387 /* Negative rectangle. */
9388 SetRect(&rect, -1, -1, 5, 5);
9389 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9390 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
9391 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9392 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
9393 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9394 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9395 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9396 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9397 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9398 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
9400 /* Out of bounds rectangle. */
9401 SetRect(&rect, 0, 0, 65, 65);
9402 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9403 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
9404 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9405 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
9407 /* Combine multiple flags. */
9408 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9409 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
9410 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
9411 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9412 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
9413 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9415 for (i = 0; i < ARRAY_SIZE(rops); i++)
9417 fx.dwROP = rops[i].rop;
9418 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9419 ok(hr == rops[i].hr, "Got unexpected hr %#lx for rop %s.\n", hr, rops[i].name);
9422 IDirectDrawSurface_Release(surface2);
9423 IDirectDrawSurface_Release(surface);
9425 memset(&surface_desc, 0, sizeof(surface_desc));
9426 surface_desc.dwSize = sizeof(surface_desc);
9427 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
9428 surface_desc.dwWidth = 64;
9429 surface_desc.dwHeight = 64;
9430 surface_desc.dwZBufferBitDepth = get_device_z_depth(device);
9431 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
9432 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9433 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9434 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
9435 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9437 /* No DDBLTFX. */
9438 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
9439 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9441 /* Unused source rectangle. */
9442 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9443 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
9445 /* Unused source surface. */
9446 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9447 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9448 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9449 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9451 /* Inverted destination or source rectangle. */
9452 SetRect(&rect, 5, 7, 7, 5);
9453 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9454 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
9455 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9456 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
9457 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9458 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9459 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9460 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9462 /* Negative rectangle. */
9463 SetRect(&rect, -1, -1, 5, 5);
9464 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9465 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
9466 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9467 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
9468 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9469 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9470 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9471 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9473 /* Out of bounds rectangle. */
9474 SetRect(&rect, 0, 0, 65, 65);
9475 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9476 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
9478 /* Combine multiple flags. */
9479 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9480 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9482 IDirectDrawSurface_Release(surface2);
9483 IDirectDrawSurface_Release(surface);
9485 done:
9486 IDirect3DDevice_Release(device);
9487 refcount = IDirectDraw_Release(ddraw);
9488 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
9489 DestroyWindow(window);
9492 static void test_colorkey_precision(void)
9494 static D3DTLVERTEX quad[] =
9496 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {0.0f}, {1.0f}},
9497 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {0.0f}, {0.0f}},
9498 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {1.0f}, {1.0f}},
9499 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {1.0f}, {0.0f}},
9501 unsigned int inst_length, data[4] = {0}, color_mask, color, t, c;
9502 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9503 IDirect3DDevice *device;
9504 IDirectDraw *ddraw;
9505 IDirectDrawSurface *rt;
9506 IDirect3DViewport *viewport;
9507 IDirect3DExecuteBuffer *execute_buffer;
9508 D3DEXECUTEBUFFERDESC exec_desc;
9509 void *ptr;
9510 HWND window;
9511 HRESULT hr;
9512 IDirectDrawSurface *src, *dst, *texture;
9513 D3DTEXTUREHANDLE handle;
9514 IDirect3DTexture *d3d_texture;
9515 IDirect3DMaterial *green;
9516 DDSURFACEDESC surface_desc, lock_desc;
9517 ULONG refcount;
9518 DDCOLORKEY ckey;
9519 DDBLTFX fx;
9520 BOOL is_nvidia, is_warp;
9521 static const struct
9523 unsigned int max, shift, bpp, clear;
9524 const char *name;
9525 BOOL skip_nv;
9526 DDPIXELFORMAT fmt;
9528 tests[] =
9531 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
9533 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
9534 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
9539 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
9541 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
9542 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
9547 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
9549 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
9550 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
9555 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
9557 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9558 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
9563 window = create_window();
9564 ddraw = create_ddraw();
9565 ok(!!ddraw, "Failed to create a ddraw object.\n");
9566 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
9568 skip("Failed to create a 3D device, skipping test.\n");
9569 DestroyWindow(window);
9570 IDirectDraw_Release(ddraw);
9571 return;
9573 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
9574 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
9576 is_nvidia = ddraw_is_nvidia(ddraw);
9577 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
9578 * (color key doesn't match although the values are equal), and a false
9579 * positive when the color key is 0 and the texture contains the value 1.
9580 * I don't want to mark this broken unconditionally since this would
9581 * essentially disable the test on Windows. Also on random occasions
9582 * 254 == 255 and 255 != 255.*/
9583 is_warp = ddraw_is_warp(ddraw);
9585 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
9586 viewport = create_viewport(device, 0, 0, 640, 480);
9587 viewport_set_background(device, viewport, green);
9589 memset(&exec_desc, 0, sizeof(exec_desc));
9590 exec_desc.dwSize = sizeof(exec_desc);
9591 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
9592 exec_desc.dwBufferSize = 1024;
9593 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
9594 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
9595 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#lx.\n", hr);
9597 memset(&fx, 0, sizeof(fx));
9598 fx.dwSize = sizeof(fx);
9599 memset(&lock_desc, 0, sizeof(lock_desc));
9600 lock_desc.dwSize = sizeof(lock_desc);
9602 for (t = 0; t < ARRAY_SIZE(tests); ++t)
9604 if (is_nvidia && tests[t].skip_nv)
9606 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
9607 continue;
9610 memset(&surface_desc, 0, sizeof(surface_desc));
9611 surface_desc.dwSize = sizeof(surface_desc);
9612 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9613 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9614 surface_desc.dwWidth = 4;
9615 surface_desc.dwHeight = 1;
9616 surface_desc.ddpfPixelFormat = tests[t].fmt;
9617 /* Windows XP (at least with the r200 driver, other drivers untested) produces
9618 * garbage when doing color keyed texture->texture blits. */
9619 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src, NULL);
9620 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9621 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst, NULL);
9622 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9624 fx.dwFillColor = tests[t].clear;
9625 /* On the w8 testbot (WARP driver) the blit result has different values in the
9626 * X channel. */
9627 color_mask = tests[t].fmt.dwRBitMask
9628 | tests[t].fmt.dwGBitMask
9629 | tests[t].fmt.dwBBitMask;
9631 for (c = 0; c <= tests[t].max; ++c)
9633 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
9634 * texture after it has been set once... */
9635 surface_desc.dwFlags |= DDSD_CKSRCBLT;
9636 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9637 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
9638 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
9639 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &texture, NULL);
9640 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9642 hr = IDirectDrawSurface_QueryInterface(texture, &IID_IDirect3DTexture, (void **)&d3d_texture);
9643 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
9644 hr = IDirect3DTexture_GetHandle(d3d_texture, device, &handle);
9645 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#lx.\n", hr);
9646 IDirect3DTexture_Release(d3d_texture);
9648 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
9649 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#lx.\n", hr);
9651 memcpy(exec_desc.lpData, quad, sizeof(quad));
9653 ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad);
9654 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
9655 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9656 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, handle);
9657 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATEALPHA);
9658 /* D3DRENDERSTATE_COLORKEYENABLE is supposed to be on by default on version
9659 * 1 devices, but for some reason it randomly defaults to FALSE on the W8
9660 * testbot. This is either the fault of Windows 8 or the WARP driver.
9661 * Also D3DRENDERSTATE_COLORKEYENABLE was introduced in D3D 5 aka version 2
9662 * devices only, which might imply this doesn't actually do anything on
9663 * WARP. */
9664 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
9666 emit_tquad(&ptr, 0);
9667 emit_tquad(&ptr, 4);
9668 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
9669 emit_end(&ptr);
9671 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
9672 inst_length -= sizeof(quad);
9673 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
9674 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#lx.\n", hr);
9675 set_execute_data(execute_buffer, 8, sizeof(quad), inst_length);
9677 hr = IDirectDrawSurface_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9678 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#lx.\n", hr);
9680 hr = IDirectDrawSurface_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
9681 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
9682 switch (tests[t].bpp)
9684 case 4:
9685 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
9686 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
9687 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
9688 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
9689 break;
9691 case 2:
9692 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
9693 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
9694 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
9695 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
9696 break;
9698 hr = IDirectDrawSurface_Unlock(src, 0);
9699 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
9700 hr = IDirectDrawSurface_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
9701 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
9703 ckey.dwColorSpaceLowValue = c << tests[t].shift;
9704 ckey.dwColorSpaceHighValue = c << tests[t].shift;
9705 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
9706 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
9708 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
9709 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
9711 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
9712 hr = IDirectDrawSurface_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
9713 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
9714 switch (tests[t].bpp)
9716 case 4:
9717 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
9718 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
9719 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
9720 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
9721 break;
9723 case 2:
9724 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
9725 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
9726 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
9727 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
9728 break;
9730 hr = IDirectDrawSurface_Unlock(dst, 0);
9731 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
9733 if (!c)
9735 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
9736 tests[t].clear, data[0], tests[t].name, c);
9738 if (data[3] == tests[t].clear)
9740 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
9741 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
9742 * even when a different surface is used. The blit itself doesn't draw anything,
9743 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
9744 * never be masked out by the key.
9746 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
9747 * test is disabled entirely.
9749 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
9750 * terrible on WARP. */
9751 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
9752 IDirectDrawSurface_Release(texture);
9753 IDirectDrawSurface_Release(src);
9754 IDirectDrawSurface_Release(dst);
9755 goto done;
9758 else
9759 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
9760 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
9762 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
9763 tests[t].clear, data[1], tests[t].name, c);
9765 if (c == tests[t].max)
9766 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
9767 tests[t].clear, data[2], tests[t].name, c);
9768 else
9769 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
9770 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
9772 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9773 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
9775 hr = IDirect3DDevice_BeginScene(device);
9776 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
9777 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
9778 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
9779 hr = IDirect3DDevice_EndScene(device);
9780 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
9782 color = get_surface_color(rt, 80, 240);
9783 if (!c)
9784 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
9785 "Got unexpected color 0x%08x, format %s, c=%u.\n",
9786 color, tests[t].name, c);
9787 else
9788 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
9789 "Got unexpected color 0x%08x, format %s, c=%u.\n",
9790 color, tests[t].name, c);
9792 color = get_surface_color(rt, 240, 240);
9793 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
9794 "Got unexpected color 0x%08x, format %s, c=%u.\n",
9795 color, tests[t].name, c);
9797 color = get_surface_color(rt, 400, 240);
9798 if (c == tests[t].max)
9799 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
9800 "Got unexpected color 0x%08x, format %s, c=%u.\n",
9801 color, tests[t].name, c);
9802 else
9803 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
9804 "Got unexpected color 0x%08x, format %s, c=%u.\n",
9805 color, tests[t].name, c);
9807 IDirectDrawSurface_Release(texture);
9809 IDirectDrawSurface_Release(src);
9810 IDirectDrawSurface_Release(dst);
9812 done:
9814 destroy_viewport(device, viewport);
9815 destroy_material(green);
9816 IDirectDrawSurface_Release(rt);
9817 IDirect3DExecuteBuffer_Release(execute_buffer);
9818 IDirect3DDevice_Release(device);
9819 refcount = IDirectDraw_Release(ddraw);
9820 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
9821 DestroyWindow(window);
9824 static void test_range_colorkey(void)
9826 IDirectDraw *ddraw;
9827 HWND window;
9828 HRESULT hr;
9829 IDirectDrawSurface *surface;
9830 DDSURFACEDESC surface_desc;
9831 ULONG refcount;
9832 DDCOLORKEY ckey;
9834 window = create_window();
9835 ddraw = create_ddraw();
9836 ok(!!ddraw, "Failed to create a ddraw object.\n");
9837 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9838 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
9840 memset(&surface_desc, 0, sizeof(surface_desc));
9841 surface_desc.dwSize = sizeof(surface_desc);
9842 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
9843 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9844 surface_desc.dwWidth = 1;
9845 surface_desc.dwHeight = 1;
9846 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
9847 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
9848 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
9849 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
9850 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
9851 surface_desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0x00000000;
9853 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
9854 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
9855 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
9856 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9857 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
9859 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
9860 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
9861 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9862 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
9864 /* Same for DDSCAPS_OFFSCREENPLAIN. */
9865 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9866 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
9867 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
9868 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9869 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
9871 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
9872 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
9873 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9874 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
9876 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
9877 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
9878 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9879 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9881 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
9882 ckey.dwColorSpaceLowValue = 0x00000000;
9883 ckey.dwColorSpaceHighValue = 0x00000001;
9884 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9885 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
9887 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9888 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
9889 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
9890 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
9892 ckey.dwColorSpaceLowValue = 0x00000001;
9893 ckey.dwColorSpaceHighValue = 0x00000000;
9894 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9895 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
9897 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9898 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
9899 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
9900 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
9902 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
9903 ckey.dwColorSpaceLowValue = 0x00000000;
9904 ckey.dwColorSpaceHighValue = 0x00000000;
9905 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9906 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
9908 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
9909 ckey.dwColorSpaceLowValue = 0x00000001;
9910 ckey.dwColorSpaceHighValue = 0x00000000;
9911 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9912 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
9913 ckey.dwColorSpaceLowValue = 0x00000000;
9914 ckey.dwColorSpaceHighValue = 0x00000001;
9915 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9916 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
9917 /* Range destination keys don't work either. */
9918 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
9919 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
9921 /* Just to show it's not because of A, R, and G having equal values. */
9922 ckey.dwColorSpaceLowValue = 0x00000000;
9923 ckey.dwColorSpaceHighValue = 0x01010101;
9924 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
9925 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
9927 /* None of these operations modified the key. */
9928 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9929 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
9930 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
9931 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
9933 IDirectDrawSurface_Release(surface);
9934 refcount = IDirectDraw_Release(ddraw);
9935 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
9936 DestroyWindow(window);
9939 static void test_shademode(void)
9941 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9942 unsigned int color0, color1, i, inst_length;
9943 IDirect3DExecuteBuffer *execute_buffer;
9944 D3DEXECUTEBUFFERDESC exec_desc;
9945 IDirect3DMaterial *background;
9946 IDirect3DViewport *viewport;
9947 IDirect3DDevice *device;
9948 IDirectDrawSurface *rt;
9949 const D3DLVERTEX *quad;
9950 IDirectDraw *ddraw;
9951 ULONG refcount;
9952 HWND window;
9953 HRESULT hr;
9954 void *ptr;
9955 static const D3DLVERTEX quad_strip[] =
9957 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
9958 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
9959 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
9960 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
9962 quad_list[] =
9964 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
9965 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
9966 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
9967 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
9969 static const struct
9971 DWORD primtype;
9972 DWORD shademode;
9973 unsigned int color0, color1;
9975 tests[] =
9977 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
9978 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
9979 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
9980 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
9981 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x000000ff, 0x0000ff00},
9982 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
9985 window = create_window();
9986 ddraw = create_ddraw();
9987 ok(!!ddraw, "Failed to create a ddraw object.\n");
9988 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
9990 skip("Failed to create a 3D device, skipping test.\n");
9991 IDirectDraw_Release(ddraw);
9992 DestroyWindow(window);
9993 return;
9996 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
9997 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
9999 background = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
10000 viewport = create_viewport(device, 0, 0, 640, 480);
10001 viewport_set_background(device, viewport, background);
10003 memset(&exec_desc, 0, sizeof(exec_desc));
10004 exec_desc.dwSize = sizeof(exec_desc);
10005 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
10006 exec_desc.dwBufferSize = 1024;
10007 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
10009 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
10010 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#lx.\n", hr);
10012 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
10013 * the color fixups we have to do for FLAT shading will be dependent on that. */
10015 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10017 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
10018 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
10020 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
10021 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#lx.\n", hr);
10023 quad = tests[i].primtype == D3DPT_TRIANGLESTRIP ? quad_strip : quad_list;
10024 memcpy(exec_desc.lpData, quad, sizeof(quad_strip));
10025 ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad_strip);
10026 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, FALSE);
10027 emit_set_rs(&ptr, D3DRENDERSTATE_FOGENABLE, FALSE);
10028 emit_set_rs(&ptr, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
10029 emit_set_rs(&ptr, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
10031 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
10032 if (tests[i].primtype == D3DPT_TRIANGLESTRIP)
10033 emit_tquad(&ptr, 0);
10034 else
10035 emit_tquad_tlist(&ptr, 0);
10036 emit_end(&ptr);
10037 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
10038 inst_length -= sizeof(quad_strip);
10040 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
10041 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#lx.\n", hr);
10043 hr = IDirect3DDevice_BeginScene(device);
10044 set_execute_data(execute_buffer, 4, sizeof(quad_strip), inst_length);
10045 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
10046 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#lx.\n", hr);
10047 hr = IDirect3DDevice_EndScene(device);
10048 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
10050 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
10051 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
10053 /* For D3DSHADE_FLAT it should take the color of the first vertex of
10054 * each triangle. This requires EXT_provoking_vertex or similar
10055 * functionality being available. */
10056 /* PHONG should be the same as GOURAUD, since no hardware implements
10057 * this. */
10058 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
10059 i, color0, tests[i].color0);
10060 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
10061 i, color1, tests[i].color1);
10064 IDirect3DExecuteBuffer_Release(execute_buffer);
10065 destroy_viewport(device, viewport);
10066 destroy_material(background);
10067 IDirectDrawSurface_Release(rt);
10068 refcount = IDirect3DDevice_Release(device);
10069 ok(!refcount, "Device has %lu references left.\n", refcount);
10070 IDirectDraw_Release(ddraw);
10071 DestroyWindow(window);
10074 static void test_lockrect_invalid(void)
10076 unsigned int i, r;
10077 IDirectDraw *ddraw;
10078 IDirectDrawSurface *surface;
10079 HWND window;
10080 HRESULT hr;
10081 DDSURFACEDESC surface_desc;
10082 DDCAPS hal_caps;
10083 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
10084 static RECT valid[] =
10086 {60, 60, 68, 68},
10087 {60, 60, 60, 68},
10088 {60, 60, 68, 60},
10089 {120, 60, 128, 68},
10090 {60, 120, 68, 128},
10092 static RECT invalid[] =
10094 {68, 60, 60, 68}, /* left > right */
10095 {60, 68, 68, 60}, /* top > bottom */
10096 {-8, 60, 0, 68}, /* left < surface */
10097 {60, -8, 68, 0}, /* top < surface */
10098 {-16, 60, -8, 68}, /* right < surface */
10099 {60, -16, 68, -8}, /* bottom < surface */
10100 {60, 60, 136, 68}, /* right > surface */
10101 {60, 60, 68, 136}, /* bottom > surface */
10102 {136, 60, 144, 68}, /* left > surface */
10103 {60, 136, 68, 144}, /* top > surface */
10105 static const struct
10107 DWORD caps;
10108 const char *name;
10109 HRESULT hr;
10111 resources[] =
10113 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, "sysmem offscreenplain", DDERR_INVALIDPARAMS},
10114 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, "vidmem offscreenplain", DDERR_INVALIDPARAMS},
10115 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "sysmem texture", DDERR_INVALIDPARAMS},
10116 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "vidmem texture", DDERR_INVALIDPARAMS},
10119 window = create_window();
10120 ddraw = create_ddraw();
10121 ok(!!ddraw, "Failed to create a ddraw object.\n");
10122 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10123 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
10125 memset(&hal_caps, 0, sizeof(hal_caps));
10126 hal_caps.dwSize = sizeof(hal_caps);
10127 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
10128 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
10129 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
10131 skip("Required surface types not supported, skipping test.\n");
10132 goto done;
10135 for (r = 0; r < ARRAY_SIZE(resources); ++r)
10137 memset(&surface_desc, 0, sizeof(surface_desc));
10138 surface_desc.dwSize = sizeof(surface_desc);
10139 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10140 surface_desc.ddsCaps.dwCaps = resources[r].caps;
10141 surface_desc.dwWidth = 128;
10142 surface_desc.dwHeight = 128;
10143 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
10144 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
10145 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
10146 surface_desc.ddpfPixelFormat.dwRBitMask = 0xff0000;
10147 surface_desc.ddpfPixelFormat.dwGBitMask = 0x00ff00;
10148 surface_desc.ddpfPixelFormat.dwBBitMask = 0x0000ff;
10150 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10151 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx, type %s.\n", hr, resources[r].name);
10153 hr = IDirectDrawSurface_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
10154 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx, type %s.\n", hr, resources[r].name);
10156 for (i = 0; i < ARRAY_SIZE(valid); ++i)
10158 RECT *rect = &valid[i];
10160 memset(&surface_desc, 0, sizeof(surface_desc));
10161 surface_desc.dwSize = sizeof(surface_desc);
10163 hr = IDirectDrawSurface_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
10164 ok(SUCCEEDED(hr), "Lock failed (%#lx) for rect %s, type %s.\n",
10165 hr, wine_dbgstr_rect(rect), resources[r].name);
10167 hr = IDirectDrawSurface_Unlock(surface, NULL);
10168 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
10171 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
10173 RECT *rect = &invalid[i];
10175 memset(&surface_desc, 1, sizeof(surface_desc));
10176 surface_desc.dwSize = sizeof(surface_desc);
10178 hr = IDirectDrawSurface_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
10179 ok(hr == resources[r].hr, "Lock returned %#lx for rect %s, type %s.\n",
10180 hr, wine_dbgstr_rect(rect), resources[r].name);
10181 if (SUCCEEDED(hr))
10183 hr = IDirectDrawSurface_Unlock(surface, NULL);
10184 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
10186 else
10187 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
10190 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
10191 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#lx, type %s.\n",
10192 hr, resources[r].name);
10193 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
10194 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#lx, type %s.\n",
10195 hr, resources[r].name);
10196 hr = IDirectDrawSurface_Unlock(surface, NULL);
10197 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
10199 hr = IDirectDrawSurface_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
10200 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#lx).\n", wine_dbgstr_rect(&valid[0]), hr);
10201 hr = IDirectDrawSurface_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
10202 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#lx).\n",
10203 wine_dbgstr_rect(&valid[0]), hr);
10205 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
10206 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
10208 hr = IDirectDrawSurface_Unlock(surface, NULL);
10209 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
10211 IDirectDrawSurface_Release(surface);
10214 done:
10215 IDirectDraw_Release(ddraw);
10216 DestroyWindow(window);
10219 static void test_yv12_overlay(void)
10221 IDirectDrawSurface *src_surface, *dst_surface;
10222 RECT rect = {13, 17, 14, 18};
10223 unsigned int offset, y;
10224 unsigned char *base;
10225 DDSURFACEDESC desc;
10226 IDirectDraw *ddraw;
10227 HWND window;
10228 HRESULT hr;
10230 window = create_window();
10231 ddraw = create_ddraw();
10232 ok(!!ddraw, "Failed to create a ddraw object.\n");
10233 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10234 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
10236 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
10238 skip("Failed to create a YV12 overlay, skipping test.\n");
10239 goto done;
10242 memset(&desc, 0, sizeof(desc));
10243 desc.dwSize = sizeof(desc);
10244 hr = IDirectDrawSurface_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
10245 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
10247 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
10248 "Got unexpected flags %#lx.\n", desc.dwFlags);
10249 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
10250 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
10251 "Got unexpected caps %#lx.\n", desc.ddsCaps.dwCaps);
10252 ok(desc.dwWidth == 256, "Got unexpected width %lu.\n", desc.dwWidth);
10253 ok(desc.dwHeight == 256, "Got unexpected height %lu.\n", desc.dwHeight);
10254 /* The overlay pitch seems to have 256 byte alignment. */
10255 ok(!(desc.lPitch & 0xff), "Got unexpected pitch %lu.\n", desc.lPitch);
10257 /* Fill the surface with some data for the blit test. */
10258 base = desc.lpSurface;
10259 /* Luminance */
10260 for (y = 0; y < desc.dwHeight; ++y)
10262 memset(base + desc.lPitch * y, 0x10, desc.dwWidth);
10264 /* V */
10265 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
10267 memset(base + desc.lPitch * y, 0x20, desc.dwWidth);
10269 /* U */
10270 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
10272 memset(base + desc.lPitch * y, 0x30, desc.dwWidth);
10275 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
10276 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
10278 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
10279 * other block-based formats like DXT the entire Y channel is stored in
10280 * one big chunk of memory, followed by the chroma channels. So partial
10281 * locks do not really make sense. Show that they are allowed nevertheless
10282 * and the offset points into the luminance data. */
10283 hr = IDirectDrawSurface_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
10284 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
10285 offset = ((const unsigned char *)desc.lpSurface - base);
10286 ok(offset == rect.top * desc.lPitch + rect.left, "Got unexpected offset %u, expected %lu.\n",
10287 offset, rect.top * desc.lPitch + rect.left);
10288 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
10289 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
10291 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
10293 /* Windows XP with a Radeon X1600 GPU refuses to create a second
10294 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
10295 skip("Failed to create a second YV12 surface, skipping blit test.\n");
10296 IDirectDrawSurface_Release(src_surface);
10297 goto done;
10300 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
10301 /* VMware rejects YV12 blits. This behavior has not been seen on real
10302 * hardware yet, so mark it broken. */
10303 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#lx.\n", hr);
10305 if (SUCCEEDED(hr))
10307 memset(&desc, 0, sizeof(desc));
10308 desc.dwSize = sizeof(desc);
10309 hr = IDirectDrawSurface_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
10310 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
10312 base = desc.lpSurface;
10313 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
10314 base += desc.dwHeight * desc.lPitch;
10315 ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
10316 base += desc.dwHeight / 4 * desc.lPitch;
10317 ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
10319 hr = IDirectDrawSurface_Unlock(dst_surface, NULL);
10320 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
10323 IDirectDrawSurface_Release(dst_surface);
10324 IDirectDrawSurface_Release(src_surface);
10325 done:
10326 IDirectDraw_Release(ddraw);
10327 DestroyWindow(window);
10330 static BOOL dwm_enabled(void)
10332 BOOL ret = FALSE;
10334 if (!strcmp(winetest_platform, "wine"))
10335 return FALSE;
10336 if (!pDwmIsCompositionEnabled)
10337 return FALSE;
10338 if (FAILED(pDwmIsCompositionEnabled(&ret)))
10339 return FALSE;
10340 return ret;
10343 static void test_offscreen_overlay(void)
10345 IDirectDrawSurface *overlay, *offscreen, *primary;
10346 DDSURFACEDESC surface_desc;
10347 IDirectDraw *ddraw;
10348 HWND window;
10349 HRESULT hr;
10350 HDC dc;
10352 window = create_window();
10353 ddraw = create_ddraw();
10354 ok(!!ddraw, "Failed to create a ddraw object.\n");
10355 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10356 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
10358 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
10360 skip("Failed to create a UYVY overlay, skipping test.\n");
10361 goto done;
10364 memset(&surface_desc, 0, sizeof(surface_desc));
10365 surface_desc.dwSize = sizeof(surface_desc);
10366 surface_desc.dwFlags = DDSD_CAPS;
10367 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
10368 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
10369 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
10371 /* On Windows 7, and probably Vista, UpdateOverlay() will return
10372 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
10373 * surface prevents this by disabling the dwm. */
10374 hr = IDirectDrawSurface_GetDC(primary, &dc);
10375 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
10376 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
10377 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
10379 /* Try to overlay a NULL surface. */
10380 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
10381 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10382 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
10383 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10385 /* Try to overlay an offscreen surface. */
10386 memset(&surface_desc, 0, sizeof(surface_desc));
10387 surface_desc.dwSize = sizeof(surface_desc);
10388 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
10389 surface_desc.dwWidth = 64;
10390 surface_desc.dwHeight = 64;
10391 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10392 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
10393 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
10394 surface_desc.ddpfPixelFormat.dwFourCC = 0;
10395 surface_desc.ddpfPixelFormat.dwRGBBitCount = 16;
10396 surface_desc.ddpfPixelFormat.dwRBitMask = 0xf800;
10397 surface_desc.ddpfPixelFormat.dwGBitMask = 0x07e0;
10398 surface_desc.ddpfPixelFormat.dwBBitMask = 0x001f;
10399 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
10400 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
10402 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
10403 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled())
10404 || broken(hr == E_NOTIMPL && ddraw_is_vmware(ddraw)),
10405 "Failed to update overlay, hr %#lx.\n", hr);
10407 /* Try to overlay the primary with a non-overlay surface. */
10408 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
10409 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#lx.\n", hr);
10410 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
10411 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#lx.\n", hr);
10413 IDirectDrawSurface_Release(offscreen);
10414 IDirectDrawSurface_Release(primary);
10415 IDirectDrawSurface_Release(overlay);
10416 done:
10417 IDirectDraw_Release(ddraw);
10418 DestroyWindow(window);
10421 static void test_overlay_rect(void)
10423 IDirectDrawSurface *overlay, *primary = NULL;
10424 DDSURFACEDESC surface_desc;
10425 RECT rect = {0, 0, 64, 64};
10426 IDirectDraw *ddraw;
10427 LONG pos_x, pos_y;
10428 HRESULT hr, hr2;
10429 HWND window;
10430 HDC dc;
10432 window = create_window();
10433 ddraw = create_ddraw();
10434 ok(!!ddraw, "Failed to create a ddraw object.\n");
10435 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10436 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
10438 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
10440 skip("Failed to create a UYVY overlay, skipping test.\n");
10441 goto done;
10444 memset(&surface_desc, 0, sizeof(surface_desc));
10445 surface_desc.dwSize = sizeof(surface_desc);
10446 surface_desc.dwFlags = DDSD_CAPS;
10447 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
10448 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
10449 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
10451 /* On Windows 7, and probably Vista, UpdateOverlay() will return
10452 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
10453 * surface prevents this by disabling the dwm. */
10454 hr = IDirectDrawSurface_GetDC(primary, &dc);
10455 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
10456 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
10457 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
10459 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
10460 if (dwm_enabled())
10462 win_skip("Cannot disable DWM, skipping overlay test.\n");
10463 goto done;
10466 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
10467 * used. This is not true in Windows Vista and earlier, but changed in
10468 * Windows 7. */
10469 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
10470 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#lx.\n", hr);
10471 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
10472 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#lx.\n", hr);
10473 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
10474 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10476 /* Show that the overlay position is the (top, left) coordinate of the
10477 * destination rectangle. */
10478 OffsetRect(&rect, 32, 16);
10479 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
10480 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#lx.\n", hr);
10481 pos_x = -1; pos_y = -1;
10482 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
10483 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#lx.\n", hr);
10484 ok(pos_x == rect.left, "Got unexpected pos_x %ld, expected %ld.\n", pos_x, rect.left);
10485 ok(pos_y == rect.top, "Got unexpected pos_y %ld, expected %ld.\n", pos_y, rect.top);
10487 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
10488 * seen that the overlay overlays the whole primary(==screen). */
10489 hr2 = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
10490 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#lx.\n", hr2);
10491 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
10492 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#lx.\n", hr);
10493 if (SUCCEEDED(hr2))
10495 ok(!pos_x, "Got unexpected pos_x %ld.\n", pos_x);
10496 ok(!pos_y, "Got unexpected pos_y %ld.\n", pos_y);
10498 else
10500 ok(pos_x == 32, "Got unexpected pos_x %ld.\n", pos_x);
10501 ok(pos_y == 16, "Got unexpected pos_y %ld.\n", pos_y);
10504 /* The position cannot be retrieved when the overlay is not shown. */
10505 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
10506 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#lx.\n", hr);
10507 pos_x = -1; pos_y = -1;
10508 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
10509 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#lx.\n", hr);
10510 ok(!pos_x, "Got unexpected pos_x %ld.\n", pos_x);
10511 ok(!pos_y, "Got unexpected pos_y %ld.\n", pos_y);
10513 done:
10514 if (primary)
10515 IDirectDrawSurface_Release(primary);
10516 if (overlay)
10517 IDirectDrawSurface_Release(overlay);
10518 IDirectDraw_Release(ddraw);
10519 DestroyWindow(window);
10522 static void test_blt(void)
10524 IDirectDrawSurface *surface, *rt;
10525 DDSURFACEDESC surface_desc;
10526 IDirect3DDevice *device;
10527 IDirectDraw *ddraw;
10528 unsigned int i;
10529 ULONG refcount;
10530 HWND window;
10531 HRESULT hr;
10533 static struct
10535 RECT src_rect;
10536 RECT dst_rect;
10537 HRESULT hr;
10539 test_data[] =
10541 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
10542 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
10543 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
10544 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
10545 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
10546 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
10547 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
10548 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
10549 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
10550 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
10553 window = create_window();
10554 ddraw = create_ddraw();
10555 ok(!!ddraw, "Failed to create a ddraw object.\n");
10556 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
10558 skip("Failed to create a 3D device, skipping test.\n");
10559 IDirectDraw_Release(ddraw);
10560 DestroyWindow(window);
10561 return;
10564 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
10565 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
10567 memset(&surface_desc, 0, sizeof(surface_desc));
10568 surface_desc.dwSize = sizeof(surface_desc);
10569 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
10570 surface_desc.dwWidth = 640;
10571 surface_desc.dwHeight = 480;
10572 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10573 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10574 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10576 hr = IDirectDrawSurface_Blt(surface, NULL, surface, NULL, 0, NULL);
10577 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
10579 hr = IDirectDrawSurface_Blt(surface, NULL, rt, NULL, 0, NULL);
10580 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
10582 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
10584 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
10585 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
10586 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n", i, hr, test_data[i].hr);
10588 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
10589 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
10590 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n", i, hr, test_data[i].hr);
10592 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
10593 NULL, &test_data[i].src_rect, DDBLT_WAIT, NULL);
10594 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10596 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect, NULL, NULL, DDBLT_WAIT, NULL);
10597 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10600 IDirectDrawSurface_Release(surface);
10601 IDirectDrawSurface_Release(rt);
10602 refcount = IDirect3DDevice_Release(device);
10603 ok(!refcount, "Device has %lu references left.\n", refcount);
10604 IDirectDraw_Release(ddraw);
10605 DestroyWindow(window);
10608 static void test_blt_z_alpha(void)
10610 DWORD blt_flags[] =
10612 /* 0 */
10613 DDBLT_ALPHADEST,
10614 DDBLT_ALPHADESTCONSTOVERRIDE,
10615 DDBLT_ALPHADESTNEG,
10616 DDBLT_ALPHADESTSURFACEOVERRIDE,
10617 DDBLT_ALPHAEDGEBLEND,
10618 /* 5 */
10619 DDBLT_ALPHASRC,
10620 DDBLT_ALPHASRCCONSTOVERRIDE,
10621 DDBLT_ALPHASRCNEG,
10622 DDBLT_ALPHASRCSURFACEOVERRIDE,
10623 DDBLT_ZBUFFER,
10624 /* 10 */
10625 DDBLT_ZBUFFERDESTCONSTOVERRIDE,
10626 DDBLT_ZBUFFERDESTOVERRIDE,
10627 DDBLT_ZBUFFERSRCCONSTOVERRIDE,
10628 DDBLT_ZBUFFERSRCOVERRIDE,
10630 IDirectDrawSurface *src_surface, *dst_surface;
10631 DDSURFACEDESC surface_desc;
10632 unsigned int color, i;
10633 IDirectDraw *ddraw;
10634 DDPIXELFORMAT pf;
10635 ULONG refcount;
10636 HWND window;
10637 HRESULT hr;
10638 DDBLTFX fx;
10640 window = create_window();
10641 ddraw = create_ddraw();
10642 ok(!!ddraw, "Failed to create a ddraw object.\n");
10643 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10644 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
10646 memset(&pf, 0, sizeof(pf));
10647 pf.dwSize = sizeof(pf);
10648 pf.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
10649 pf.dwRGBBitCount = 32;
10650 pf.dwRBitMask = 0x00ff0000;
10651 pf.dwGBitMask = 0x0000ff00;
10652 pf.dwBBitMask = 0x000000ff;
10653 pf.dwRGBAlphaBitMask = 0xff000000;
10655 memset(&surface_desc, 0, sizeof(surface_desc));
10656 surface_desc.dwSize = sizeof(surface_desc);
10657 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
10658 surface_desc.dwWidth = 64;
10659 surface_desc.dwHeight = 64;
10660 surface_desc.ddpfPixelFormat = pf;
10661 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10663 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
10664 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#lx.\n", hr);
10665 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
10666 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#lx.\n", hr);
10668 memset(&fx, 0, sizeof(fx));
10669 fx.dwSize = sizeof(fx);
10670 fx.dwZBufferOpCode = D3DCMP_NEVER;
10671 fx.dwZDestConstBitDepth = 32;
10672 fx.dwZDestConst = 0x11111111;
10673 fx.dwZSrcConstBitDepth = 32;
10674 fx.dwZSrcConst = 0xeeeeeeee;
10675 fx.dwAlphaEdgeBlendBitDepth = 8;
10676 fx.dwAlphaEdgeBlend = 0x7f;
10677 fx.dwAlphaDestConstBitDepth = 8;
10678 fx.dwAlphaDestConst = 0xdd;
10679 fx.dwAlphaSrcConstBitDepth = 8;
10680 fx.dwAlphaSrcConst = 0x22;
10682 for (i = 0; i < ARRAY_SIZE(blt_flags); ++i)
10684 fx.dwFillColor = 0x3300ff00;
10685 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10686 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#lx.\n", i, hr);
10688 fx.dwFillColor = 0xccff0000;
10689 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10690 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#lx.\n", i, hr);
10692 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, NULL, blt_flags[i] | DDBLT_WAIT, &fx);
10693 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#lx.\n", i, hr);
10695 color = get_surface_color(dst_surface, 32, 32);
10696 ok(compare_color(color, 0x0000ff00, 0), "Test %u: Got unexpected color 0x%08x.\n", i, color);
10699 IDirectDrawSurface_Release(dst_surface);
10700 IDirectDrawSurface_Release(src_surface);
10701 refcount = IDirectDraw_Release(ddraw);
10702 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
10703 DestroyWindow(window);
10706 static void test_cross_device_blt(void)
10708 IDirectDrawSurface *surface, *surface2, *sysmem_surface;
10709 IDirect3DDevice *device, *device2;
10710 IDirectDraw *ddraw, *ddraw2;
10711 DDSURFACEDESC surface_desc;
10712 HWND window, window2;
10713 unsigned int color;
10714 ULONG refcount;
10715 DDBLTFX fx;
10716 HRESULT hr;
10718 window = create_window();
10719 ddraw = create_ddraw();
10720 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
10722 skip("Failed to create a 3D device.\n");
10723 IDirectDraw_Release(ddraw);
10724 DestroyWindow(window);
10725 return;
10728 window2 = create_window();
10729 ddraw2 = create_ddraw();
10730 if (!(device2 = create_device(ddraw2, window2, DDSCL_NORMAL)))
10732 skip("Failed to create a 3D device.\n");
10733 IDirectDraw_Release(ddraw2);
10734 IDirect3DDevice_Release(device);
10735 IDirectDraw_Release(ddraw);
10736 DestroyWindow(window);
10737 DestroyWindow(window2);
10738 return;
10741 memset(&surface_desc, 0, sizeof(surface_desc));
10742 surface_desc.dwSize = sizeof(surface_desc);
10743 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
10744 surface_desc.dwWidth = 640;
10745 surface_desc.dwHeight = 480;
10746 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10747 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
10748 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10750 memset(&surface_desc, 0, sizeof(surface_desc));
10751 surface_desc.dwSize = sizeof(surface_desc);
10752 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
10753 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
10754 surface_desc.dwBackBufferCount = 2;
10755 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10756 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10758 memset(&surface_desc, 0, sizeof(surface_desc));
10759 surface_desc.dwSize = sizeof(surface_desc);
10760 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
10761 surface_desc.dwWidth = 640;
10762 surface_desc.dwHeight = 480;
10763 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10764 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
10765 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
10766 surface_desc.ddpfPixelFormat.dwRGBBitCount = 16;
10767 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00007c00;
10768 surface_desc.ddpfPixelFormat.dwGBitMask = 0x000003e0;
10769 surface_desc.ddpfPixelFormat.dwBBitMask = 0x0000001f;
10770 hr = IDirectDraw_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
10771 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10773 memset(&fx, 0, sizeof(fx));
10774 fx.dwSize = sizeof(fx);
10775 fx.dwFillColor = 0xff0000ff;
10776 hr = IDirectDrawSurface_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10777 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#lx.\n", hr);
10779 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
10780 ok(hr == E_NOTIMPL, "Got unexpected hr %#lx.\n", hr);
10781 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
10782 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10783 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
10784 ok(hr == E_NOTIMPL, "Got unexpected hr %#lx.\n", hr);
10785 color = get_surface_color(surface, 320, 240);
10786 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
10788 hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
10789 ok(hr == E_NOTIMPL, "Got unexpected hr %#lx.\n", hr);
10790 color = get_surface_color(sysmem_surface, 320, 240);
10791 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
10793 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10794 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
10795 hr = IDirectDrawSurface_IsLost(sysmem_surface);
10796 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10798 hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
10799 ok(hr == E_NOTIMPL, "Got unexpected hr %#lx.\n", hr);
10800 color = get_surface_color(sysmem_surface, 320, 240);
10801 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
10803 IDirectDrawSurface_Release(surface2);
10804 memset(&surface_desc, 0, sizeof(surface_desc));
10805 surface_desc.dwSize = sizeof(surface_desc);
10806 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
10807 surface_desc.dwWidth = 640;
10808 surface_desc.dwHeight = 480;
10809 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10810 hr = IDirectDraw_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
10811 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10812 hr = IDirectDrawSurface_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10813 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#lx.\n", hr);
10815 hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
10816 todo_wine ok(hr == D3D_OK, "Failed to blit, hr %#lx.\n", hr);
10817 color = get_surface_color(sysmem_surface, 320, 240);
10818 todo_wine ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
10820 IDirectDrawSurface_Release(surface);
10821 IDirectDrawSurface_Release(surface2);
10822 IDirectDrawSurface_Release(sysmem_surface);
10823 refcount = IDirect3DDevice_Release(device);
10824 ok(!refcount, "Device has %lu references left.\n", refcount);
10825 refcount = IDirect3DDevice_Release(device2);
10826 ok(!refcount, "Device has %lu references left.\n", refcount);
10827 IDirectDraw_Release(ddraw);
10828 IDirectDraw_Release(ddraw2);
10829 DestroyWindow(window);
10830 DestroyWindow(window2);
10833 static void test_getdc(void)
10835 IDirectDrawSurface *surface, *surface2, *tmp;
10836 DDSURFACEDESC surface_desc, map_desc;
10837 DDSCAPS caps = {DDSCAPS_COMPLEX};
10838 IDirectDraw *ddraw;
10839 unsigned int i, screen_bpp;
10840 HWND window;
10841 HDC dc, dc2;
10842 HRESULT hr;
10844 static const struct
10846 const char *name;
10847 DDPIXELFORMAT format;
10848 BOOL getdc_supported;
10849 HRESULT alt_result;
10851 test_data[] =
10853 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
10854 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
10855 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
10856 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
10857 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
10858 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
10859 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
10860 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
10861 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
10862 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
10863 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
10864 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
10865 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
10866 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
10867 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
10868 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
10869 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
10870 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
10871 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
10872 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
10873 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
10874 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
10875 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
10876 * This is not implemented in wine yet, so disable the test for now.
10877 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
10878 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
10879 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
10881 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
10882 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
10883 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
10884 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
10885 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
10886 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
10887 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
10888 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
10889 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
10890 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
10891 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
10892 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
10893 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
10894 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
10897 window = create_window();
10898 ddraw = create_ddraw();
10899 ok(!!ddraw, "Failed to create a ddraw object.\n");
10900 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10901 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
10903 surface_desc.dwSize = sizeof(surface_desc);
10904 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
10905 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#lx.\n", hr);
10906 screen_bpp = surface_desc.ddpfPixelFormat.dwRGBBitCount;
10908 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
10910 memset(&surface_desc, 0, sizeof(surface_desc));
10911 surface_desc.dwSize = sizeof(surface_desc);
10912 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10913 surface_desc.dwWidth = 64;
10914 surface_desc.dwHeight = 64;
10915 surface_desc.ddpfPixelFormat = test_data[i].format;
10916 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10918 if (FAILED(IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
10920 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10921 if (FAILED(hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
10923 skip("Failed to create surface for format %s (hr %#lx), skipping tests.\n", test_data[i].name, hr);
10924 continue;
10928 dc = (void *)0x1234;
10929 hr = IDirectDrawSurface_GetDC(surface, &dc);
10930 if (test_data[i].getdc_supported)
10931 ok(SUCCEEDED(hr) || broken(hr == test_data[i].alt_result || ddraw_is_vmware(ddraw)),
10932 "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
10933 else
10934 ok(FAILED(hr), "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
10936 if (SUCCEEDED(hr))
10938 unsigned int width_bytes;
10939 DIBSECTION dib;
10940 HBITMAP bitmap;
10941 DWORD type;
10942 int size;
10944 type = GetObjectType(dc);
10945 ok(type == OBJ_MEMDC, "Got unexpected object type %#lx for format %s.\n", type, test_data[i].name);
10946 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
10947 type = GetObjectType(bitmap);
10948 ok(type == OBJ_BITMAP, "Got unexpected object type %#lx for format %s.\n", type, test_data[i].name);
10950 size = GetObjectA(bitmap, sizeof(dib), &dib);
10951 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
10952 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
10953 dib.dsBm.bmType, test_data[i].name);
10954 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
10955 dib.dsBm.bmWidth, test_data[i].name);
10956 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
10957 dib.dsBm.bmHeight, test_data[i].name);
10958 width_bytes = ((dib.dsBm.bmWidth * test_data[i].format.dwRGBBitCount + 31) >> 3) & ~3;
10959 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
10960 dib.dsBm.bmWidthBytes, test_data[i].name);
10961 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
10962 dib.dsBm.bmPlanes, test_data[i].name);
10963 ok(dib.dsBm.bmBitsPixel == test_data[i].format.dwRGBBitCount,
10964 "Got unexpected bit count %d for format %s.\n",
10965 dib.dsBm.bmBitsPixel, test_data[i].name);
10966 /* Windows XP sets bmBits == NULL for formats that match the screen at least on my r200 GPU. I
10967 * suspect this applies to all HW accelerated pre-WDDM drivers because they can handle gdi access
10968 * to ddraw surfaces themselves instead of going through a sysmem DIB section. */
10969 ok(!!dib.dsBm.bmBits || broken(!pDwmIsCompositionEnabled && dib.dsBm.bmBitsPixel == screen_bpp),
10970 "Got unexpected bits %p for format %s.\n", dib.dsBm.bmBits, test_data[i].name);
10972 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %lu for format %s.\n",
10973 dib.dsBmih.biSize, test_data[i].name);
10974 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %ld for format %s.\n",
10975 dib.dsBmih.biHeight, test_data[i].name);
10976 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %ld for format %s.\n",
10977 dib.dsBmih.biHeight, test_data[i].name);
10978 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
10979 dib.dsBmih.biPlanes, test_data[i].name);
10980 ok(dib.dsBmih.biBitCount == test_data[i].format.dwRGBBitCount,
10981 "Got unexpected bit count %u for format %s.\n",
10982 dib.dsBmih.biBitCount, test_data[i].name);
10983 ok(dib.dsBmih.biCompression == (test_data[i].format.dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
10984 || broken(test_data[i].format.dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
10985 "Got unexpected compression %#lx for format %s.\n",
10986 dib.dsBmih.biCompression, test_data[i].name);
10987 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %lu for format %s.\n",
10988 dib.dsBmih.biSizeImage, test_data[i].name);
10989 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %ld for format %s.\n",
10990 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
10991 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %ld for format %s.\n",
10992 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
10993 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %lu for format %s.\n",
10994 dib.dsBmih.biClrUsed, test_data[i].name);
10995 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %lu for format %s.\n",
10996 dib.dsBmih.biClrImportant, test_data[i].name);
10998 if (dib.dsBmih.biCompression == BI_BITFIELDS)
11000 ok((dib.dsBitfields[0] == test_data[i].format.dwRBitMask
11001 && dib.dsBitfields[1] == test_data[i].format.dwGBitMask
11002 && dib.dsBitfields[2] == test_data[i].format.dwBBitMask)
11003 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
11004 "Got unexpected colour masks 0x%08lx 0x%08lx 0x%08lx for format %s.\n",
11005 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11007 else
11009 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
11010 "Got unexpected colour masks 0x%08lx 0x%08lx 0x%08lx for format %s.\n",
11011 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11013 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
11014 ok(!dib.dsOffset, "Got unexpected offset %lu for format %s.\n", dib.dsOffset, test_data[i].name);
11016 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11017 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11019 else
11021 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
11024 IDirectDrawSurface_Release(surface);
11026 if (FAILED(hr))
11027 continue;
11029 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
11030 if (FAILED(hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11032 skip("Failed to create mip-mapped texture for format %s (hr %#lx), skipping tests.\n",
11033 test_data[i].name, hr);
11034 continue;
11037 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
11038 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11039 hr = IDirectDrawSurface_GetAttachedSurface(tmp, &caps, &surface2);
11040 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11041 IDirectDrawSurface_Release(tmp);
11043 hr = IDirectDrawSurface_GetDC(surface, &dc);
11044 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11045 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11046 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11047 hr = IDirectDrawSurface_GetDC(surface2, &dc);
11048 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11049 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
11050 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11052 hr = IDirectDrawSurface_GetDC(surface, &dc);
11053 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11054 dc2 = (void *)0x1234;
11055 hr = IDirectDrawSurface_GetDC(surface, &dc2);
11056 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11057 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
11058 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11059 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11060 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11061 ok(hr == DDERR_NODC, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11063 map_desc.dwSize = sizeof(map_desc);
11064 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11065 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11066 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11067 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11068 hr = IDirectDrawSurface_Unlock(surface, NULL);
11069 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11070 hr = IDirectDrawSurface_Unlock(surface, NULL);
11071 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11073 hr = IDirectDrawSurface_GetDC(surface, &dc);
11074 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11075 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11076 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11077 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11078 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11080 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11081 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11082 hr = IDirectDrawSurface_GetDC(surface, &dc);
11083 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11084 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11085 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11086 /* Geforce 9600, Windows 7 returns E_FAIL. The unlock still seems to work as intended, after-
11087 * wards the surface can be locked again. ReleaseDC() does not unlock the surface, trying to
11088 * Lock it after ReleaseDC returns DDERR_SURFACEBUSY. ddraw4 and 7 are unaffected. */
11089 hr = IDirectDrawSurface_Unlock(surface, NULL);
11090 ok(SUCCEEDED(hr) || broken(ddraw_is_nvidia(ddraw) && hr == E_FAIL),
11091 "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11093 hr = IDirectDrawSurface_GetDC(surface, &dc);
11094 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11095 hr = IDirectDrawSurface_GetDC(surface2, &dc2);
11096 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11097 hr = IDirectDrawSurface_ReleaseDC(surface2, dc2);
11098 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11099 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11100 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11102 hr = IDirectDrawSurface_GetDC(surface2, &dc);
11103 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11104 hr = IDirectDrawSurface_GetDC(surface, &dc2);
11105 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11106 hr = IDirectDrawSurface_ReleaseDC(surface, dc2);
11107 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11108 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
11109 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11111 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11112 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11113 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11114 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11115 hr = IDirectDrawSurface_Unlock(surface2, NULL);
11116 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11117 hr = IDirectDrawSurface_Unlock(surface, NULL);
11118 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11120 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11121 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11122 hr = IDirectDrawSurface_GetDC(surface, &dc);
11123 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11124 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11125 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11126 hr = IDirectDrawSurface_Unlock(surface, NULL);
11127 ok(SUCCEEDED(hr) || broken(ddraw_is_nvidia(ddraw) && hr == E_FAIL),
11128 "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11130 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11131 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11132 hr = IDirectDrawSurface_GetDC(surface, &dc);
11133 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11134 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11135 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11136 hr = IDirectDrawSurface_Unlock(surface2, NULL);
11137 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11139 hr = IDirectDrawSurface_GetDC(surface, &dc);
11140 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11141 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11142 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11143 hr = IDirectDrawSurface_Unlock(surface2, NULL);
11144 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11145 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11146 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11148 hr = IDirectDrawSurface_GetDC(surface2, &dc);
11149 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11150 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11151 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11152 hr = IDirectDrawSurface_Unlock(surface, NULL);
11153 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11154 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
11155 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11157 hr = IDirectDrawSurface_Unlock(surface, NULL);
11158 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11159 hr = IDirectDrawSurface_GetDC(surface2, &dc);
11160 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11161 hr = IDirectDrawSurface_Unlock(surface, NULL);
11162 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11163 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
11164 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11165 hr = IDirectDrawSurface_Unlock(surface, NULL);
11166 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11168 hr = IDirectDrawSurface_Unlock(surface2, NULL);
11169 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11170 hr = IDirectDrawSurface_GetDC(surface, &dc);
11171 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11172 hr = IDirectDrawSurface_Unlock(surface2, NULL);
11173 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11174 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11175 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11176 hr = IDirectDrawSurface_Unlock(surface2, NULL);
11177 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11179 IDirectDrawSurface_Release(surface2);
11180 IDirectDrawSurface_Release(surface);
11183 IDirectDraw_Release(ddraw);
11184 DestroyWindow(window);
11187 /* TransformVertices always writes 32 bytes regardless of the input / output stride.
11188 * The stride is honored for navigating to the next vertex. 3 floats input position
11189 * are read, and 16 bytes extra vertex data are copied around. */
11190 struct transform_input
11192 float x, y, z, unused1; /* Position data, transformed. */
11193 DWORD v1, v2, v3, v4; /* Extra data, e.g. color and texture coords, copied. */
11194 DWORD unused2;
11197 struct transform_output
11199 float x, y, z, w;
11200 unsigned int v1, v2, v3, v4;
11201 unsigned int unused3, unused4;
11204 static void test_transform_vertices(void)
11206 unsigned int inst_length, color;
11207 IDirect3DDevice *device;
11208 IDirectDrawSurface *rt;
11209 IDirectDraw *ddraw;
11210 ULONG refcount;
11211 HWND window;
11212 HRESULT hr;
11213 IDirect3DViewport *viewport;
11214 IDirect3DExecuteBuffer *execute_buffer;
11215 IDirect3DMaterial *background;
11216 D3DEXECUTEBUFFERDESC exec_desc;
11217 void *ptr;
11218 D3DMATRIXHANDLE world_handle, view_handle, proj_handle;
11219 static struct transform_input position_tests[] =
11221 { 0.0f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
11222 { 1.0f, 1.0f, 1.0f, 8.0f, 6, 7, 8, 9, 10},
11223 {-1.0f, -1.0f, -1.0f, 4.0f, 11, 12, 13, 14, 15},
11224 { 0.5f, 0.5f, 0.5f, 2.0f, 16, 17, 18, 19, 20},
11225 {-0.5f, -0.5f, -0.5f, 1.0f, ~1U, ~2U, ~3U, ~4U, ~5U},
11226 {-0.5f, -0.5f, 0.0f, 0.0f, ~6U, ~7U, ~8U, ~9U, ~0U},
11228 static struct transform_input cliptest[] =
11230 { 25.59f, 25.59f, 1.0f, 0.0f, 1, 2, 3, 4, 5},
11231 { 25.61f, 25.61f, 1.01f, 0.0f, 1, 2, 3, 4, 5},
11232 {-25.59f, -25.59f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
11233 {-25.61f, -25.61f, -0.01f, 0.0f, 1, 2, 3, 4, 5},
11235 static struct transform_input offscreentest[] =
11237 {128.1f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
11239 struct transform_output out[ARRAY_SIZE(position_tests)];
11240 D3DHVERTEX out_h[ARRAY_SIZE(position_tests)];
11241 D3DTRANSFORMDATA transformdata;
11242 static const D3DVIEWPORT vp_template =
11244 sizeof(vp_template), 0, 0, 256, 256, 5.0f, 5.0f, 256.0f, 256.0f, -25.0f, 60.0f
11246 D3DVIEWPORT vp_data =
11248 sizeof(vp_data), 0, 0, 256, 256, 1.0f, 1.0f, 256.0f, 256.0f, 0.0f, 1.0f
11250 unsigned int i;
11251 DWORD offscreen;
11252 static D3DMATRIX mat_scale =
11254 2.0f, 0.0f, 0.0f, 0.0f,
11255 0.0f, 2.0f, 0.0f, 0.0f,
11256 0.0f, 0.0f, 2.0f, 0.0f,
11257 0.0f, 0.0f, 0.0f, 1.0f,
11259 mat_translate1 =
11261 1.0f, 0.0f, 0.0f, 0.0f,
11262 0.0f, 1.0f, 0.0f, 0.0f,
11263 0.0f, 0.0f, 1.0f, 0.0f,
11264 1.0f, 0.0f, 0.0f, 1.0f,
11266 mat_translate2 =
11268 1.0f, 0.0f, 0.0f, 0.0f,
11269 0.0f, 1.0f, 0.0f, 0.0f,
11270 0.0f, 0.0f, 1.0f, 0.0f,
11271 0.0f, 1.0f, 0.0f, 1.0f,
11273 static const D3DLVERTEX quad[] =
11275 {{-0.75f},{-0.5f }, {0.0f}, 0, {0xffff0000}},
11276 {{-0.75f},{ 0.25f}, {0.0f}, 0, {0xffff0000}},
11277 {{ 0.5f}, {-0.5f }, {0.0f}, 0, {0xffff0000}},
11278 {{ 0.5f}, { 0.25f}, {0.0f}, 0, {0xffff0000}},
11280 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
11283 for (i = 0; i < ARRAY_SIZE(out); ++i)
11285 out[i].unused3 = 0xdeadbeef;
11286 out[i].unused4 = 0xcafecafe;
11289 window = create_window();
11290 ddraw = create_ddraw();
11291 ok(!!ddraw, "Failed to create a ddraw object.\n");
11292 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
11294 skip("Failed to create a 3D device, skipping test.\n");
11295 IDirectDraw_Release(ddraw);
11296 DestroyWindow(window);
11297 return;
11300 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
11301 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
11303 viewport = create_viewport(device, 0, 0, 256, 256);
11304 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
11305 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
11307 memset(&transformdata, 0, sizeof(transformdata));
11308 transformdata.dwSize = sizeof(transformdata);
11309 transformdata.lpIn = position_tests;
11310 transformdata.dwInSize = sizeof(position_tests[0]);
11311 transformdata.lpOut = out;
11312 transformdata.dwOutSize = sizeof(out[0]);
11313 transformdata.lpHOut = NULL;
11315 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
11316 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11317 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11318 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
11320 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
11322 static const struct vec4 cmp[] =
11324 {128.0f, 128.0f, 0.0f, 1.0f}, {129.0f, 127.0f, 1.0f, 1.0f}, {127.0f, 129.0f, -1.0f, 1.0f},
11325 {128.5f, 127.5f, 0.5f, 1.0f}, {127.5f, 128.5f, -0.5f, 1.0f}, {127.5f, 128.5f, 0.0f, 1.0f}
11328 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
11329 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
11330 out[i].x, out[i].y, out[i].z, out[i].w);
11331 ok(out[i].v1 == position_tests[i].v1 && out[i].v2 == position_tests[i].v2
11332 && out[i].v3 == position_tests[i].v3 && out[i].v4 == position_tests[i].v4,
11333 "Vertex %u payload is %u %u %u %u.\n", i, out[i].v1, out[i].v2, out[i].v3, out[i].v4);
11334 ok(out[i].unused3 == 0xdeadbeef && out[i].unused4 == 0xcafecafe,
11335 "Vertex %u unused data is %#x, %#x.\n", i, out[i].unused3, out[i].unused4);
11338 vp_data = vp_template;
11339 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
11340 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
11341 offscreen = 0xdeadbeef;
11342 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
11343 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11344 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11345 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
11347 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
11349 static const struct vec4 cmp[] =
11351 {128.0f, 128.0f, 0.0f, 1.0f}, {133.0f, 123.0f, 1.0f, 1.0f}, {123.0f, 133.0f, -1.0f, 1.0f},
11352 {130.5f, 125.5f, 0.5f, 1.0f}, {125.5f, 130.5f, -0.5f, 1.0f}, {125.5f, 130.5f, 0.0f, 1.0f}
11354 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
11355 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
11356 out[i].x, out[i].y, out[i].z, out[i].w);
11359 vp_data.dwX = 10;
11360 vp_data.dwY = 20;
11361 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
11362 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
11363 offscreen = 0xdeadbeef;
11364 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
11365 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11366 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11367 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
11368 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
11370 static const struct vec4 cmp[] =
11372 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, {133.0f, 153.0f, -1.0f, 1.0f},
11373 {140.5f, 145.5f, 0.5f, 1.0f}, {135.5f, 150.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
11375 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
11376 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
11377 out[i].x, out[i].y, out[i].z, out[i].w);
11380 transformdata.lpHOut = out_h;
11381 offscreen = 0xdeadbeef;
11382 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
11383 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11384 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11385 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
11386 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
11388 static const D3DHVERTEX cmp_h[] =
11390 {0, { 0.0f}, { 0.0f}, { 0.0f}}, {0, { 1.0f}, { 1.0f}, {1.0f}},
11391 {D3DCLIP_FRONT, {-1.0f}, {-1.0f}, {-1.0f}}, {0, { 0.5f}, { 0.5f}, {0.5f}},
11392 {D3DCLIP_FRONT, {-0.5f}, {-0.5f}, {-0.5f}}, {0, {-0.5f}, {-0.5f}, {0.0f}}
11394 ok(compare_float(cmp_h[i].hx, out_h[i].hx, 4096)
11395 && compare_float(cmp_h[i].hy, out_h[i].hy, 4096)
11396 && compare_float(cmp_h[i].hz, out_h[i].hz, 4096)
11397 && cmp_h[i].dwFlags == out_h[i].dwFlags,
11398 "HVertex %u differs. Got %#lx %.8e %.8e %.8e.\n", i,
11399 out_h[i].dwFlags, out_h[i].hx, out_h[i].hy, out_h[i].hz);
11401 /* No scheme has been found behind those return values. It seems to be
11402 * whatever data windows has when throwing the vertex away. Modify the
11403 * input test vertices to test this more. Depending on the input data
11404 * it can happen that the z coord gets written into y, or similar things. */
11405 if (0)
11407 static const struct vec4 cmp[] =
11409 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, { -1.0f, -1.0f, 0.5f, 1.0f},
11410 {140.5f, 145.5f, 0.5f, 1.0f}, { -0.5f, -0.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
11412 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
11413 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
11414 out[i].x, out[i].y, out[i].z, out[i].w);
11418 transformdata.lpIn = cliptest;
11419 transformdata.dwInSize = sizeof(cliptest[0]);
11420 offscreen = 0xdeadbeef;
11421 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(cliptest),
11422 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11423 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11424 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
11425 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
11427 static const DWORD flags[] =
11430 D3DCLIP_RIGHT | D3DCLIP_BACK | D3DCLIP_TOP,
11432 D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
11434 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#lx.\n", i, out_h[i].dwFlags);
11437 vp_data = vp_template;
11438 vp_data.dwWidth = 10;
11439 vp_data.dwHeight = 1000;
11440 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
11441 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
11442 offscreen = 0xdeadbeef;
11443 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(cliptest),
11444 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11445 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11446 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
11447 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
11449 static const DWORD flags[] =
11451 D3DCLIP_RIGHT,
11452 D3DCLIP_RIGHT | D3DCLIP_BACK,
11453 D3DCLIP_LEFT,
11454 D3DCLIP_LEFT | D3DCLIP_FRONT,
11456 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#lx.\n", i, out_h[i].dwFlags);
11459 vp_data = vp_template;
11460 vp_data.dwWidth = 256;
11461 vp_data.dwHeight = 256;
11462 vp_data.dvScaleX = 1;
11463 vp_data.dvScaleY = 1;
11464 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
11465 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
11466 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(cliptest),
11467 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11468 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11469 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
11470 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
11472 static const DWORD flags[] =
11475 D3DCLIP_BACK,
11477 D3DCLIP_FRONT,
11479 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#lx.\n", i, out_h[i].dwFlags);
11482 /* Finally try to figure out how the DWORD dwOffscreen works.
11483 * It is a logical AND of the vertices' dwFlags members. */
11484 vp_data = vp_template;
11485 vp_data.dwWidth = 5;
11486 vp_data.dwHeight = 5;
11487 vp_data.dvScaleX = 10000.0f;
11488 vp_data.dvScaleY = 10000.0f;
11489 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
11490 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
11491 transformdata.lpIn = cliptest;
11492 offscreen = 0xdeadbeef;
11493 hr = IDirect3DViewport_TransformVertices(viewport, 1,
11494 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11495 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11496 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
11498 offscreen = 0xdeadbeef;
11499 hr = IDirect3DViewport_TransformVertices(viewport, 1,
11500 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11501 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11502 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %#lx.\n", offscreen);
11503 offscreen = 0xdeadbeef;
11504 hr = IDirect3DViewport_TransformVertices(viewport, 2,
11505 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11506 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11507 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %#lx.\n", offscreen);
11508 hr = IDirect3DViewport_TransformVertices(viewport, 3,
11509 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11510 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11511 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
11513 transformdata.lpIn = cliptest + 1;
11514 hr = IDirect3DViewport_TransformVertices(viewport, 1,
11515 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11516 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11517 ok(offscreen == (D3DCLIP_BACK | D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %#lx.\n", offscreen);
11519 transformdata.lpIn = cliptest + 2;
11520 hr = IDirect3DViewport_TransformVertices(viewport, 1,
11521 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11522 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11523 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %#lx.\n", offscreen);
11524 offscreen = 0xdeadbeef;
11525 hr = IDirect3DViewport_TransformVertices(viewport, 2,
11526 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11527 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11528 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %#lx.\n", offscreen);
11530 transformdata.lpIn = cliptest + 3;
11531 hr = IDirect3DViewport_TransformVertices(viewport, 1,
11532 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11533 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11534 ok(offscreen == (D3DCLIP_FRONT | D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %#lx.\n", offscreen);
11536 transformdata.lpIn = offscreentest;
11537 transformdata.dwInSize = sizeof(offscreentest[0]);
11538 vp_data = vp_template;
11539 vp_data.dwWidth = 257;
11540 vp_data.dwHeight = 257;
11541 vp_data.dvScaleX = 1.0f;
11542 vp_data.dvScaleY = 1.0f;
11543 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
11544 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
11545 offscreen = 0xdeadbeef;
11546 hr = IDirect3DViewport_TransformVertices(viewport, 1,
11547 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11548 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11549 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
11551 vp_data.dwWidth = 256;
11552 vp_data.dwHeight = 256;
11553 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
11554 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
11555 hr = IDirect3DViewport_TransformVertices(viewport, 1,
11556 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11557 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11558 ok(offscreen == D3DCLIP_RIGHT, "Offscreen is %#lx.\n", offscreen);
11560 /* Test the effect of Matrices.
11562 * Basically the x coordinate ends up as ((x + 1) * 2 + 0) * 5 and
11563 * y as ((y + 0) * 2 + 1) * 5. The 5 comes from dvScaleX/Y, 2 from
11564 * the view matrix and the +1's from the world and projection matrix. */
11565 vp_data.dwX = 0;
11566 vp_data.dwY = 0;
11567 vp_data.dwWidth = 256;
11568 vp_data.dwHeight = 256;
11569 vp_data.dvScaleX = 5.0f;
11570 vp_data.dvScaleY = 5.0f;
11571 vp_data.dvMinZ = 0.0f;
11572 vp_data.dvMaxZ = 1.0f;
11573 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
11574 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
11576 hr = IDirect3DDevice_CreateMatrix(device, &world_handle);
11577 ok(hr == D3D_OK, "Creating a matrix object failed, hr %#lx.\n", hr);
11578 hr = IDirect3DDevice_SetMatrix(device, world_handle, &mat_translate1);
11579 ok(hr == D3D_OK, "Setting a matrix object failed, hr %#lx.\n", hr);
11581 hr = IDirect3DDevice_CreateMatrix(device, &view_handle);
11582 ok(hr == D3D_OK, "Creating a matrix object failed, hr %#lx.\n", hr);
11583 hr = IDirect3DDevice_SetMatrix(device, view_handle, &mat_scale);
11584 ok(hr == D3D_OK, "Setting a matrix object failed, hr %#lx.\n", hr);
11586 hr = IDirect3DDevice_CreateMatrix(device, &proj_handle);
11587 ok(hr == D3D_OK, "Creating a matrix object failed, hr %#lx.\n", hr);
11588 hr = IDirect3DDevice_SetMatrix(device, proj_handle, &mat_translate2);
11589 ok(hr == D3D_OK, "Setting a matrix object failed, hr %#lx.\n", hr);
11591 memset(&exec_desc, 0, sizeof(exec_desc));
11592 exec_desc.dwSize = sizeof(exec_desc);
11593 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
11594 exec_desc.dwBufferSize = 1024;
11595 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
11596 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
11597 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#lx.\n", hr);
11599 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
11600 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#lx.\n", hr);
11601 ptr = (BYTE *)exec_desc.lpData;
11602 emit_set_ts(&ptr, D3DTRANSFORMSTATE_WORLD, world_handle);
11603 emit_set_ts(&ptr, D3DTRANSFORMSTATE_VIEW, view_handle);
11604 emit_set_ts(&ptr, D3DTRANSFORMSTATE_PROJECTION, proj_handle);
11605 emit_end(&ptr);
11606 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
11607 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
11608 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#lx.\n", hr);
11610 set_execute_data(execute_buffer, 0, 0, inst_length);
11611 hr = IDirect3DDevice_BeginScene(device);
11612 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
11613 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
11614 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#lx.\n", hr);
11615 hr = IDirect3DDevice_EndScene(device);
11616 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
11618 transformdata.lpIn = position_tests;
11619 transformdata.dwInSize = sizeof(position_tests[0]);
11620 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
11621 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11622 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11624 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
11626 static const struct vec4 cmp[] =
11628 {138.0f, 123.0f, 0.0f, 1.0f}, {148.0f, 113.0f, 2.0f, 1.0f}, {128.0f, 133.0f, -2.0f, 1.0f},
11629 {143.0f, 118.0f, 1.0f, 1.0f}, {133.0f, 128.0f, -1.0f, 1.0f}, {133.0f, 128.0f, 0.0f, 1.0f}
11632 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
11633 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
11634 out[i].x, out[i].y, out[i].z, out[i].w);
11637 /* Invalid flags. */
11638 offscreen = 0xdeadbeef;
11639 hr = IDirect3DViewport_TransformVertices(viewport, ARRAY_SIZE(position_tests),
11640 &transformdata, 0, &offscreen);
11641 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
11642 ok(offscreen == 0xdeadbeef, "Offscreen is %#lx.\n", offscreen);
11644 /* NULL transform data. */
11645 hr = IDirect3DViewport_TransformVertices(viewport, 1,
11646 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
11647 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
11648 ok(offscreen == 0xdeadbeef, "Offscreen is %#lx.\n", offscreen);
11649 hr = IDirect3DViewport_TransformVertices(viewport, 0,
11650 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
11651 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
11652 ok(offscreen == 0xdeadbeef, "Offscreen is %#lx.\n", offscreen);
11654 /* NULL transform data and NULL dwOffscreen.
11656 * Valid transform data + NULL dwOffscreen -> crash. */
11657 hr = IDirect3DViewport_TransformVertices(viewport, 1,
11658 NULL, D3DTRANSFORM_UNCLIPPED, NULL);
11659 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
11661 /* No vertices. */
11662 hr = IDirect3DViewport_TransformVertices(viewport, 0,
11663 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11664 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11665 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
11666 hr = IDirect3DViewport_TransformVertices(viewport, 0,
11667 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11668 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11669 ok(offscreen == ~0u, "Offscreen is %#lx.\n", offscreen);
11671 /* Invalid sizes. */
11672 offscreen = 0xdeadbeef;
11673 transformdata.dwSize = sizeof(transformdata) - 1;
11674 hr = IDirect3DViewport_TransformVertices(viewport, 1,
11675 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11676 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
11677 ok(offscreen == 0xdeadbeef, "Offscreen is %#lx.\n", offscreen);
11678 transformdata.dwSize = sizeof(transformdata) + 1;
11679 hr = IDirect3DViewport_TransformVertices(viewport, 1,
11680 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
11681 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
11682 ok(offscreen == 0xdeadbeef, "Offscreen is %#lx.\n", offscreen);
11684 /* NULL lpIn or lpOut -> crash, except when transforming 0 vertices. */
11685 transformdata.dwSize = sizeof(transformdata);
11686 transformdata.lpIn = NULL;
11687 transformdata.lpOut = NULL;
11688 offscreen = 0xdeadbeef;
11689 hr = IDirect3DViewport_TransformVertices(viewport, 0,
11690 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
11691 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
11692 ok(offscreen == ~0u, "Offscreen is %#lx.\n", offscreen);
11694 /* Test how vertices are transformed by execute buffers. */
11695 vp_data.dwX = 20;
11696 vp_data.dwY = 20;
11697 vp_data.dwWidth = 200;
11698 vp_data.dwHeight = 400;
11699 vp_data.dvScaleX = 20.0f;
11700 vp_data.dvScaleY = 50.0f;
11701 vp_data.dvMinZ = 0.0f;
11702 vp_data.dvMaxZ = 1.0f;
11703 hr = IDirect3DViewport_SetViewport(viewport, &vp_data);
11704 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
11706 background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 0.0f);
11707 viewport_set_background(device, viewport, background);
11708 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11709 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
11711 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
11712 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#lx.\n", hr);
11713 memcpy(exec_desc.lpData, quad, sizeof(quad));
11714 ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad);
11715 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
11716 emit_tquad(&ptr, 0);
11717 emit_end(&ptr);
11718 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
11719 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
11720 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#lx.\n", hr);
11722 set_execute_data(execute_buffer, 4, sizeof(quad), inst_length);
11723 hr = IDirect3DDevice_BeginScene(device);
11724 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
11725 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
11726 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#lx.\n", hr);
11727 hr = IDirect3DDevice_EndScene(device);
11728 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
11730 color = get_surface_color(rt, 128, 143);
11731 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
11732 color = get_surface_color(rt, 132, 143);
11733 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
11734 color = get_surface_color(rt, 128, 147);
11735 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
11736 color = get_surface_color(rt, 132, 147);
11737 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
11739 color = get_surface_color(rt, 177, 217);
11740 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
11741 color = get_surface_color(rt, 181, 217);
11742 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
11743 color = get_surface_color(rt, 177, 221);
11744 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
11745 color = get_surface_color(rt, 181, 221);
11746 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
11748 IDirect3DDevice_DeleteMatrix(device, world_handle);
11749 IDirect3DDevice_DeleteMatrix(device, view_handle);
11750 IDirect3DDevice_DeleteMatrix(device, proj_handle);
11751 IDirect3DExecuteBuffer_Release(execute_buffer);
11753 IDirectDrawSurface_Release(rt);
11754 destroy_viewport(device, viewport);
11755 IDirect3DMaterial_Release(background);
11756 refcount = IDirect3DDevice_Release(device);
11757 ok(!refcount, "Device has %lu references left.\n", refcount);
11758 IDirectDraw_Release(ddraw);
11759 DestroyWindow(window);
11762 static void test_display_mode_surface_pixel_format(void)
11764 unsigned int width, height, bpp;
11765 IDirectDrawSurface *surface;
11766 DDSURFACEDESC surface_desc;
11767 IDirectDraw *ddraw;
11768 ULONG refcount;
11769 HWND window;
11770 HRESULT hr;
11772 if (!(ddraw = create_ddraw()))
11774 skip("Failed to create ddraw.\n");
11775 return;
11778 surface_desc.dwSize = sizeof(surface_desc);
11779 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
11780 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#lx.\n", hr);
11781 width = surface_desc.dwWidth;
11782 height = surface_desc.dwHeight;
11784 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
11785 0, 0, width, height, NULL, NULL, NULL, NULL);
11786 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
11787 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
11789 bpp = 0;
11790 if (SUCCEEDED(IDirectDraw_SetDisplayMode(ddraw, width, height, 16)))
11791 bpp = 16;
11792 if (SUCCEEDED(IDirectDraw_SetDisplayMode(ddraw, width, height, 24)))
11793 bpp = 24;
11794 if (SUCCEEDED(IDirectDraw_SetDisplayMode(ddraw, width, height, 32)))
11795 bpp = 32;
11796 ok(bpp, "Set display mode failed.\n");
11798 surface_desc.dwSize = sizeof(surface_desc);
11799 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
11800 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#lx.\n", hr);
11801 ok(surface_desc.dwWidth == width, "Got width %lu, expected %u.\n", surface_desc.dwWidth, width);
11802 ok(surface_desc.dwHeight == height, "Got height %lu, expected %u.\n", surface_desc.dwHeight, height);
11803 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == bpp, "Got bpp %lu, expected %u.\n",
11804 surface_desc.ddpfPixelFormat.dwRGBBitCount, bpp);
11806 memset(&surface_desc, 0, sizeof(surface_desc));
11807 surface_desc.dwSize = sizeof(surface_desc);
11808 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
11809 surface_desc.dwBackBufferCount = 1;
11810 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
11811 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11812 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
11813 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
11814 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
11815 ok(surface_desc.dwWidth == width, "Got width %lu, expected %u.\n", surface_desc.dwWidth, width);
11816 ok(surface_desc.dwHeight == height, "Got height %lu, expected %u.\n", surface_desc.dwHeight, height);
11817 ok(surface_desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#lx.\n",
11818 surface_desc.ddpfPixelFormat.dwFlags);
11819 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == bpp, "Got bpp %lu, expected %u.\n",
11820 surface_desc.ddpfPixelFormat.dwRGBBitCount, bpp);
11821 IDirectDrawSurface_Release(surface);
11823 memset(&surface_desc, 0, sizeof(surface_desc));
11824 surface_desc.dwSize = sizeof(surface_desc);
11825 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
11826 surface_desc.dwWidth = width;
11827 surface_desc.dwHeight = height;
11828 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11829 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11830 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
11831 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
11832 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
11833 ok(surface_desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#lx.\n",
11834 surface_desc.ddpfPixelFormat.dwFlags);
11835 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == bpp, "Got bpp %lu, expected %u.\n",
11836 surface_desc.ddpfPixelFormat.dwRGBBitCount, bpp);
11837 IDirectDrawSurface_Release(surface);
11839 refcount = IDirectDraw_Release(ddraw);
11840 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
11841 DestroyWindow(window);
11844 static void test_surface_desc_size(void)
11846 union
11848 DWORD dwSize;
11849 DDSURFACEDESC desc1;
11850 DDSURFACEDESC2 desc2;
11851 BYTE blob[1024];
11852 } desc;
11853 IDirectDrawSurface7 *surface7;
11854 IDirectDrawSurface *surface;
11855 DDSURFACEDESC surface_desc;
11856 HRESULT expected_hr, hr;
11857 IDirectDraw *ddraw;
11858 unsigned int i, j;
11859 ULONG refcount;
11861 static const struct
11863 unsigned int caps;
11864 const char *name;
11866 surface_caps[] =
11868 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
11869 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
11870 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
11872 static const unsigned int desc_sizes[] =
11874 sizeof(DDSURFACEDESC),
11875 sizeof(DDSURFACEDESC2),
11876 sizeof(DDSURFACEDESC) + 1,
11877 sizeof(DDSURFACEDESC2) + 1,
11878 2 * sizeof(DDSURFACEDESC),
11879 2 * sizeof(DDSURFACEDESC2),
11880 sizeof(DDSURFACEDESC) - 1,
11881 sizeof(DDSURFACEDESC2) - 1,
11882 sizeof(DDSURFACEDESC) / 2,
11883 sizeof(DDSURFACEDESC2) / 2,
11887 sizeof(desc) / 2,
11888 sizeof(desc) - 100,
11891 if (!(ddraw = create_ddraw()))
11893 skip("Failed to create ddraw.\n");
11894 return;
11896 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
11897 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
11899 for (i = 0; i < ARRAY_SIZE(surface_caps); ++i)
11901 memset(&surface_desc, 0, sizeof(surface_desc));
11902 surface_desc.dwSize = sizeof(surface_desc);
11903 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
11904 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
11905 surface_desc.dwHeight = 128;
11906 surface_desc.dwWidth = 128;
11907 if (FAILED(IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11909 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
11910 continue;
11912 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface7, (void **)&surface7);
11913 ok(hr == DD_OK, "Failed to query IDirectDrawSurface7, hr %#lx, type %s.\n", hr, surface_caps[i].name);
11915 /* GetSurfaceDesc() */
11916 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
11918 memset(&desc, 0, sizeof(desc));
11919 desc.dwSize = desc_sizes[j];
11920 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
11921 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
11922 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
11923 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
11925 memset(&desc, 0, sizeof(desc));
11926 desc.dwSize = desc_sizes[j];
11927 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
11928 hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
11929 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
11930 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
11933 /* Lock() */
11934 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
11936 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
11937 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
11938 DWORD expected_texture_stage;
11940 memset(&desc, 0, sizeof(desc));
11941 desc.dwSize = desc_sizes[j];
11942 desc.desc2.dwTextureStage = 0xdeadbeef;
11943 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
11944 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
11945 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
11946 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
11947 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
11948 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %lu, type %s.\n",
11949 desc_sizes[j], desc.dwSize, surface_caps[i].name);
11950 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, size %u, type %s.\n",
11951 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
11952 if (SUCCEEDED(hr))
11954 ok(desc.desc1.dwWidth == 128, "Got unexpected width %lu, size %u, type %s.\n",
11955 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
11956 ok(desc.desc1.dwHeight == 128, "Got unexpected height %lu, size %u, type %s.\n",
11957 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
11958 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
11959 todo_wine_if(!expected_texture_stage)
11960 ok(desc.desc2.dwTextureStage == expected_texture_stage,
11961 "Got unexpected texture stage %#lx, size %u, type %s.\n",
11962 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
11963 IDirectDrawSurface_Unlock(surface, NULL);
11966 memset(&desc, 0, sizeof(desc));
11967 desc.dwSize = desc_sizes[j];
11968 desc.desc2.dwTextureStage = 0xdeadbeef;
11969 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
11970 hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
11971 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
11972 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
11973 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
11974 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %lu, type %s.\n",
11975 desc_sizes[j], desc.dwSize, surface_caps[i].name);
11976 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, size %u, type %s.\n",
11977 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
11978 if (SUCCEEDED(hr))
11980 ok(desc.desc2.dwWidth == 128, "Got unexpected width %lu, size %u, type %s.\n",
11981 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
11982 ok(desc.desc2.dwHeight == 128, "Got unexpected height %lu, size %u, type %s.\n",
11983 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
11984 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
11985 ok(desc.desc2.dwTextureStage == expected_texture_stage,
11986 "Got unexpected texture stage %#lx, size %u, type %s.\n",
11987 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
11988 IDirectDrawSurface7_Unlock(surface7, NULL);
11992 IDirectDrawSurface7_Release(surface7);
11993 IDirectDrawSurface_Release(surface);
11996 /* GetDisplayMode() */
11997 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
11999 memset(&desc, 0xcc, sizeof(desc));
12000 desc.dwSize = desc_sizes[j];
12001 expected_hr = (desc.dwSize == sizeof(DDSURFACEDESC) || desc.dwSize == sizeof(DDSURFACEDESC2))
12002 ? DD_OK : DDERR_INVALIDPARAMS;
12003 hr = IDirectDraw_GetDisplayMode(ddraw, &desc.desc1);
12004 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u.\n", hr, expected_hr, desc_sizes[j]);
12005 if (SUCCEEDED(hr))
12007 ok(desc.dwSize == sizeof(DDSURFACEDESC), "Wrong size %lu for %u.\n", desc.dwSize, desc_sizes[j]);
12008 ok(desc.blob[desc_sizes[j]] == 0xcc, "Overflow for size %u.\n", desc_sizes[j]);
12009 ok(desc.blob[desc_sizes[j] - 1] != 0xcc, "Struct not cleared for size %u.\n", desc_sizes[j]);
12013 refcount = IDirectDraw_Release(ddraw);
12014 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
12017 static void test_texture_load(void)
12019 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
12020 static D3DTLVERTEX tquad[] =
12022 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
12023 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
12024 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
12025 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
12027 D3DTEXTUREHANDLE dst_texture_handle, src_texture_handle;
12028 IDirectDrawSurface *dst_surface, *src_surface;
12029 IDirect3DExecuteBuffer *execute_buffer;
12030 unsigned int inst_length, color;
12031 D3DEXECUTEBUFFERDESC exec_desc;
12032 IDirect3DMaterial *background;
12033 IDirect3DViewport *viewport;
12034 DDSURFACEDESC surface_desc;
12035 IDirect3DTexture *texture;
12036 IDirect3DDevice *device;
12037 IDirectDrawSurface *rt;
12038 IDirectDraw *ddraw;
12039 ULONG refcount;
12040 HWND window;
12041 DDBLTFX fx;
12042 HRESULT hr;
12043 void *ptr;
12045 window = create_window();
12046 ddraw = create_ddraw();
12047 ok(!!ddraw, "Failed to create a ddraw object.\n");
12048 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
12050 skip("Failed to create a 3D device, skipping test.\n");
12051 IDirectDraw_Release(ddraw);
12052 DestroyWindow(window);
12053 return;
12056 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
12057 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
12059 background = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
12060 viewport = create_viewport(device, 0, 0, 640, 480);
12061 viewport_set_background(device, viewport, background);
12063 memset(&exec_desc, 0, sizeof(exec_desc));
12064 exec_desc.dwSize = sizeof(exec_desc);
12065 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
12066 exec_desc.dwBufferSize = 1024;
12067 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
12068 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
12069 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#lx.\n", hr);
12071 memset(&surface_desc, 0, sizeof(surface_desc));
12072 surface_desc.dwSize = sizeof(surface_desc);
12073 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12074 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
12075 surface_desc.dwWidth = 256;
12076 surface_desc.dwHeight = 256;
12077 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
12078 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
12079 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
12080 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
12081 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
12082 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
12084 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
12085 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
12086 hr = IDirectDrawSurface_QueryInterface(src_surface, &IID_IDirect3DTexture, (void **)&texture);
12087 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
12088 hr = IDirect3DTexture_GetHandle(texture, device, &src_texture_handle);
12089 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#lx.\n", hr);
12090 IDirect3DTexture_Release(texture);
12092 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
12093 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
12094 hr = IDirectDrawSurface_QueryInterface(dst_surface, &IID_IDirect3DTexture, (void **)&texture);
12095 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
12096 hr = IDirect3DTexture_GetHandle(texture, device, &dst_texture_handle);
12097 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#lx.\n", hr);
12098 IDirect3DTexture_Release(texture);
12100 memset(&fx, 0, sizeof(fx));
12101 fx.dwSize = sizeof(fx);
12102 fx.dwFillColor = 0x0000ffff;
12103 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12104 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#lx.\n", hr);
12106 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
12107 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#lx.\n", hr);
12108 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
12109 ptr = (BYTE *)exec_desc.lpData + sizeof(tquad);
12110 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
12111 emit_texture_load(&ptr, dst_texture_handle, src_texture_handle);
12112 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, dst_texture_handle);
12113 /* WARP randomly applies color keying without having a key set. */
12114 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, FALSE);
12115 emit_tquad(&ptr, 0);
12116 emit_end(&ptr);
12117 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData - sizeof(tquad);
12118 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
12119 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#lx.\n", hr);
12121 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
12122 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
12123 color = get_surface_color(rt, 320, 240);
12124 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
12125 set_execute_data(execute_buffer, 4, sizeof(tquad), inst_length);
12126 hr = IDirect3DDevice_BeginScene(device);
12127 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
12128 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
12129 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#lx.\n", hr);
12130 hr = IDirect3DDevice_EndScene(device);
12131 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
12132 color = get_surface_color(rt, 320, 240);
12133 ok(compare_color(color, 0x0000ffff, 1), "Got unexpected color 0x%08x.\n", color);
12135 memset(&fx, 0, sizeof(fx));
12136 fx.dwSize = sizeof(fx);
12137 fx.dwFillColor = 0x000000ff;
12138 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12139 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#lx.\n", hr);
12141 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
12142 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
12143 color = get_surface_color(rt, 320, 240);
12144 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
12145 set_execute_data(execute_buffer, 4, sizeof(tquad), inst_length);
12146 hr = IDirect3DDevice_BeginScene(device);
12147 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
12148 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
12149 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#lx.\n", hr);
12150 hr = IDirect3DDevice_EndScene(device);
12151 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
12152 color = get_surface_color(rt, 320, 240);
12153 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12155 IDirectDrawSurface_Release(dst_surface);
12156 IDirectDrawSurface_Release(src_surface);
12157 IDirectDrawSurface_Release(rt);
12158 IDirect3DExecuteBuffer_Release(execute_buffer);
12159 IDirect3DMaterial_Release(background);
12160 destroy_viewport(device, viewport);
12161 IDirect3DDevice_Release(device);
12162 refcount = IDirectDraw_Release(ddraw);
12163 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
12164 DestroyWindow(window);
12167 static void test_ck_operation(void)
12169 IDirectDrawSurface *src, *dst;
12170 IDirectDrawSurface7 *src7, *dst7;
12171 DDSURFACEDESC surface_desc;
12172 unsigned int i, *color;
12173 IDirectDraw *ddraw;
12174 ULONG refcount;
12175 HWND window;
12176 HRESULT hr;
12177 DDCOLORKEY ckey;
12178 DDBLTFX fx;
12180 window = create_window();
12181 ddraw = create_ddraw();
12182 ok(!!ddraw, "Failed to create a ddraw object.\n");
12183 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12184 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
12186 memset(&surface_desc, 0, sizeof(surface_desc));
12187 surface_desc.dwSize = sizeof(surface_desc);
12188 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12189 surface_desc.dwWidth = 4;
12190 surface_desc.dwHeight = 1;
12191 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12192 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
12193 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
12194 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
12195 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
12196 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
12197 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst, NULL);
12198 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
12200 surface_desc.dwFlags |= DDSD_CKSRCBLT;
12201 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
12202 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff;
12203 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src, NULL);
12204 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
12206 hr = IDirectDrawSurface_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12207 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12208 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
12209 color = surface_desc.lpSurface;
12210 color[0] = 0x77010203;
12211 color[1] = 0x00010203;
12212 color[2] = 0x77ff00ff;
12213 color[3] = 0x00ff00ff;
12214 hr = IDirectDrawSurface_Unlock(src, NULL);
12215 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12217 for (i = 0; i < 2; ++i)
12219 hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12220 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12221 color = surface_desc.lpSurface;
12222 color[0] = 0xcccccccc;
12223 color[1] = 0xcccccccc;
12224 color[2] = 0xcccccccc;
12225 color[3] = 0xcccccccc;
12226 hr = IDirectDrawSurface_Unlock(dst, NULL);
12227 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12229 if (i)
12231 hr = IDirectDrawSurface_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY);
12232 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
12234 else
12236 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL);
12237 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
12240 hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL);
12241 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12242 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
12243 color = surface_desc.lpSurface;
12244 /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
12245 * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for
12246 * color keying, but do not copy it into the destination surface. Nvidia neither uses it for
12247 * color keying nor copies it. */
12248 ok((color[0] == 0x77010203 && color[1] == 0x00010203
12249 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */
12250 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
12251 && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */
12252 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
12253 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */
12254 || broken(color[0] == 0xff010203 && color[1] == 0xff010203
12255 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */,
12256 "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n",
12257 color[0], color[1], color[2], color[3], i);
12258 hr = IDirectDrawSurface_Unlock(dst, NULL);
12259 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12262 hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12263 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
12264 ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff,
12265 "Got unexpected color key low=%08lx high=%08lx.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12267 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
12268 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12269 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
12271 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12272 hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12273 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
12274 ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00,
12275 "Got unexpected color key low=%08lx high=%08lx.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12277 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
12278 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
12279 hr = IDirectDrawSurface_GetSurfaceDesc(src, &surface_desc);
12280 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
12281 ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00
12282 && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00,
12283 "Got unexpected color key low=%08lx high=%08lx.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
12284 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
12286 /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
12287 ckey.dwColorSpaceLowValue = 0x000000ff;
12288 ckey.dwColorSpaceHighValue = 0x00000000;
12289 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12290 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
12292 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12293 hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12294 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
12295 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
12296 "Got unexpected color key low=%08lx high=%08lx.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12298 ckey.dwColorSpaceLowValue = 0x000000ff;
12299 ckey.dwColorSpaceHighValue = 0x00000001;
12300 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12301 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
12303 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12304 hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12305 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
12306 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
12307 "Got unexpected color key low=%08lx high=%08lx.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12309 ckey.dwColorSpaceLowValue = 0x000000fe;
12310 ckey.dwColorSpaceHighValue = 0x000000fd;
12311 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12312 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
12314 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12315 hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12316 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
12317 ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe,
12318 "Got unexpected color key low=%08lx high=%08lx.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12320 IDirectDrawSurface_Release(src);
12321 IDirectDrawSurface_Release(dst);
12323 /* Test source and destination keys and where they are read from. Use a surface with alpha
12324 * to avoid driver-dependent content in the X channel. */
12325 memset(&surface_desc, 0, sizeof(surface_desc));
12326 surface_desc.dwSize = sizeof(surface_desc);
12327 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12328 surface_desc.dwWidth = 6;
12329 surface_desc.dwHeight = 1;
12330 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12331 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12332 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
12333 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
12334 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
12335 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
12336 surface_desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
12337 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst, NULL);
12338 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
12339 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src, NULL);
12340 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
12342 ckey.dwColorSpaceLowValue = 0x0000ff00;
12343 ckey.dwColorSpaceHighValue = 0x0000ff00;
12344 hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
12345 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
12346 ckey.dwColorSpaceLowValue = 0x00ff0000;
12347 ckey.dwColorSpaceHighValue = 0x00ff0000;
12348 hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_DESTBLT, &ckey);
12349 ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#lx.\n", hr);
12350 if (FAILED(hr))
12352 /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */
12353 skip("Failed to set destination color key, skipping related tests.\n");
12354 goto done;
12357 ckey.dwColorSpaceLowValue = 0x000000ff;
12358 ckey.dwColorSpaceHighValue = 0x000000ff;
12359 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12360 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
12361 ckey.dwColorSpaceLowValue = 0x000000aa;
12362 ckey.dwColorSpaceHighValue = 0x000000aa;
12363 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_DESTBLT, &ckey);
12364 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
12366 memset(&fx, 0, sizeof(fx));
12367 fx.dwSize = sizeof(fx);
12368 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000;
12369 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000;
12370 fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100;
12371 fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100;
12373 hr = IDirectDrawSurface_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12374 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12375 color = surface_desc.lpSurface;
12376 color[0] = 0x000000ff; /* Applies to src blt key in src surface. */
12377 color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */
12378 color[2] = 0x00ff0000; /* Dst color key in dst surface. */
12379 color[3] = 0x0000ff00; /* Src color key in dst surface. */
12380 color[4] = 0x00001100; /* Src color key in ddbltfx. */
12381 color[5] = 0x00110000; /* Dst color key in ddbltfx. */
12382 hr = IDirectDrawSurface_Unlock(src, NULL);
12383 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12385 hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12386 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12387 color = surface_desc.lpSurface;
12388 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12389 hr = IDirectDrawSurface_Unlock(dst, NULL);
12390 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12392 /* Test a blit without keying. */
12393 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, 0, &fx);
12394 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
12396 hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12397 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12398 color = surface_desc.lpSurface;
12399 /* Should have copied src data unmodified to dst. */
12400 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
12401 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
12402 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12403 color[0], color[1], color[2], color[3], color[4], color[5]);
12405 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12406 hr = IDirectDrawSurface_Unlock(dst, NULL);
12407 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12409 /* Src key. */
12410 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
12411 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
12413 hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12414 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12415 color = surface_desc.lpSurface;
12416 /* Src key applied to color[0]. It is unmodified, the others are copied. */
12417 ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
12418 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
12419 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12420 color[0], color[1], color[2], color[3], color[4], color[5]);
12422 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12423 hr = IDirectDrawSurface_Unlock(dst, NULL);
12424 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12426 /* Src override. */
12427 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
12428 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
12430 hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12431 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12432 color = surface_desc.lpSurface;
12433 /* Override key applied to color[5]. It is unmodified, the others are copied. */
12434 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
12435 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555,
12436 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12437 color[0], color[1], color[2], color[3], color[4], color[5]);
12439 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12440 hr = IDirectDrawSurface_Unlock(dst, NULL);
12441 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12443 /* Src override AND src key. That is not supposed to work. */
12444 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
12445 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
12447 hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12448 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12449 color = surface_desc.lpSurface;
12450 /* Ensure the destination was not changed. */
12451 ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 &&
12452 color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555,
12453 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12454 color[0], color[1], color[2], color[3], color[4], color[5]);
12456 /* Use different dst colors for the dst key test. */
12457 color[0] = 0x00ff0000; /* Dest key in dst surface. */
12458 color[1] = 0x00ff0000; /* Dest key in dst surface. */
12459 color[2] = 0x00001100; /* Dest key in override. */
12460 color[3] = 0x00001100; /* Dest key in override. */
12461 color[4] = 0x000000aa; /* Dest key in src surface. */
12462 color[5] = 0x000000aa; /* Dest key in src surface. */
12463 hr = IDirectDrawSurface_Unlock(dst, NULL);
12464 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12466 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
12467 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
12469 hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12470 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12471 color = surface_desc.lpSurface;
12472 /* Dst key applied to color[4,5], they are the only changed pixels. */
12473 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
12474 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
12475 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12476 color[0], color[1], color[2], color[3], color[4], color[5]);
12478 color[0] = 0x00ff0000; /* Dest key in dst surface. */
12479 color[1] = 0x00ff0000; /* Dest key in dst surface. */
12480 color[2] = 0x00001100; /* Dest key in override. */
12481 color[3] = 0x00001100; /* Dest key in override. */
12482 color[4] = 0x000000aa; /* Dest key in src surface. */
12483 color[5] = 0x000000aa; /* Dest key in src surface. */
12484 hr = IDirectDrawSurface_Unlock(dst, NULL);
12485 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12487 /* What happens with a QI'd newer version of the interface? It takes the key
12488 * from the destination surface. */
12489 hr = IDirectDrawSurface_QueryInterface(src, &IID_IDirectDrawSurface7, (void **)&src7);
12490 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#lx.\n", hr);
12491 hr = IDirectDrawSurface_QueryInterface(dst, &IID_IDirectDrawSurface7, (void **)&dst7);
12492 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#lx.\n", hr);
12494 hr = IDirectDrawSurface7_Blt(dst7, NULL, src7, NULL, DDBLT_KEYDEST, &fx);
12495 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
12497 IDirectDrawSurface7_Release(dst7);
12498 IDirectDrawSurface7_Release(src7);
12500 hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12501 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12502 color = surface_desc.lpSurface;
12503 /* Dst key applied to color[0,1], they are the only changed pixels. */
12504 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
12505 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
12506 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12507 color[0], color[1], color[2], color[3], color[4], color[5]);
12509 color[0] = 0x00ff0000; /* Dest key in dst surface. */
12510 color[1] = 0x00ff0000; /* Dest key in dst surface. */
12511 color[2] = 0x00001100; /* Dest key in override. */
12512 color[3] = 0x00001100; /* Dest key in override. */
12513 color[4] = 0x000000aa; /* Dest key in src surface. */
12514 color[5] = 0x000000aa; /* Dest key in src surface. */
12515 hr = IDirectDrawSurface_Unlock(dst, NULL);
12516 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12518 /* Dest override key blit. */
12519 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
12520 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
12522 hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12523 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12524 color = surface_desc.lpSurface;
12525 /* Dst key applied to color[2,3], they are the only changed pixels. */
12526 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 &&
12527 color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa,
12528 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12529 color[0], color[1], color[2], color[3], color[4], color[5]);
12531 color[0] = 0x00ff0000; /* Dest key in dst surface. */
12532 color[1] = 0x00ff0000; /* Dest key in dst surface. */
12533 color[2] = 0x00001100; /* Dest key in override. */
12534 color[3] = 0x00001100; /* Dest key in override. */
12535 color[4] = 0x000000aa; /* Dest key in src surface. */
12536 color[5] = 0x000000aa; /* Dest key in src surface. */
12537 hr = IDirectDrawSurface_Unlock(dst, NULL);
12538 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12540 /* Dest override together with surface key. Supposed to fail. */
12541 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
12542 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
12544 hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12545 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12546 color = surface_desc.lpSurface;
12547 /* Destination is unchanged. */
12548 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
12549 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
12550 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12551 color[0], color[1], color[2], color[3], color[4], color[5]);
12552 hr = IDirectDrawSurface_Unlock(dst, NULL);
12553 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12555 /* Source and destination key. This is driver dependent. New HW treats it like
12556 * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */
12557 if (0)
12559 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
12560 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
12562 hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12563 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12564 color = surface_desc.lpSurface;
12565 /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if
12566 * the driver applies it. */
12567 ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
12568 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
12569 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12570 color[0], color[1], color[2], color[3], color[4], color[5]);
12572 color[0] = 0x00ff0000; /* Dest key in dst surface. */
12573 color[1] = 0x00ff0000; /* Dest key in dst surface. */
12574 color[2] = 0x00001100; /* Dest key in override. */
12575 color[3] = 0x00001100; /* Dest key in override. */
12576 color[4] = 0x000000aa; /* Dest key in src surface. */
12577 color[5] = 0x000000aa; /* Dest key in src surface. */
12578 hr = IDirectDrawSurface_Unlock(dst, NULL);
12579 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12582 /* Override keys without ddbltfx parameter fail */
12583 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
12584 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
12585 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
12586 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
12588 /* Try blitting without keys in the source surface. */
12589 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, NULL);
12590 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
12591 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_DESTBLT, NULL);
12592 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
12594 /* That fails now. Do not bother to check that the data is unmodified. */
12595 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
12596 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
12598 /* Surprisingly this still works. It uses the old key from the src surface. */
12599 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
12600 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
12602 hr = IDirectDrawSurface_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12603 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12604 color = surface_desc.lpSurface;
12605 /* Dst key applied to color[4,5], they are the only changed pixels. */
12606 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
12607 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
12608 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12609 color[0], color[1], color[2], color[3], color[4], color[5]);
12610 hr = IDirectDrawSurface_Unlock(dst, NULL);
12611 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12613 /* This returns DDERR_NOCOLORKEY as expected. */
12614 hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_DESTBLT, &ckey);
12615 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx.\n", hr);
12617 /* GetSurfaceDesc returns a zeroed key as expected. */
12618 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x12345678;
12619 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x12345678;
12620 hr = IDirectDrawSurface_GetSurfaceDesc(src, &surface_desc);
12621 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
12622 ok(!surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue
12623 && !surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue,
12624 "Got unexpected color key low=%08lx high=%08lx.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
12625 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
12627 /* Try blitting without keys in the destination surface. */
12628 hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_SRCBLT, NULL);
12629 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
12630 hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_DESTBLT, NULL);
12631 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
12633 /* This is weird. It makes sense in v4 and v7, but because v1
12634 * uses the key from the src surface it makes no sense here. */
12635 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
12636 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
12638 done:
12639 IDirectDrawSurface_Release(src);
12640 IDirectDrawSurface_Release(dst);
12641 refcount = IDirectDraw_Release(ddraw);
12642 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
12643 DestroyWindow(window);
12646 static void test_depth_readback(void)
12648 unsigned int depth, expected_depth, inst_length, max_diff, x, y;
12649 IDirect3DExecuteBuffer *execute_buffer;
12650 IDirect3DMaterial *blue_background;
12651 D3DEXECUTEBUFFERDESC exec_desc;
12652 IDirectDrawSurface *rt, *ds;
12653 IDirect3DViewport *viewport;
12654 DDSURFACEDESC surface_desc;
12655 IDirect3DDevice *device;
12656 DWORD z_depth, z_mask;
12657 IDirectDraw *ddraw;
12658 ULONG refcount;
12659 HWND window;
12660 HRESULT hr;
12661 void *ptr;
12663 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
12664 static D3DLVERTEX quad[] =
12666 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0xff00ff00}},
12667 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
12668 {{ 1.0f}, {-1.0f}, {1.0f}, 0, {0xff00ff00}},
12669 {{ 1.0f}, { 1.0f}, {0.9f}, 0, {0xff00ff00}},
12672 window = create_window();
12673 ok(!!window, "Failed to create a window.\n");
12674 ddraw = create_ddraw();
12675 ok(!!ddraw, "Failed to create a ddraw object.\n");
12676 if (ddraw_is_nvidia(ddraw))
12678 /* ddraw1 only has access to D16 Z buffers (and D24 ones, which are even more
12679 * broken on Nvidia), so don't even attempt to run this test on Nvidia cards
12680 * because some of them have broken D16 readback. See the ddraw7 version of
12681 * this test for a more detailed comment. */
12682 skip("Some Nvidia GPUs have broken D16 readback, skipping.\n");
12683 IDirectDraw_Release(ddraw);
12684 DestroyWindow(window);
12685 return;
12688 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
12690 skip("Failed to create a D3D device, skipping tests.\n");
12691 IDirectDraw_Release(ddraw);
12692 DestroyWindow(window);
12693 return;
12696 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
12697 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
12698 z_depth = get_device_z_depth(device);
12699 z_mask = 0xffffffff >> (32 - z_depth);
12700 ds = get_depth_stencil(device);
12702 /* Changing depth buffers is hard in d3d1, so we only test with the
12703 * initial depth buffer here. */
12705 blue_background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
12706 viewport = create_viewport(device, 0, 0, 640, 480);
12707 viewport_set_background(device, viewport, blue_background);
12709 memset(&exec_desc, 0, sizeof(exec_desc));
12710 exec_desc.dwSize = sizeof(exec_desc);
12711 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
12712 exec_desc.dwBufferSize = 1024;
12713 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
12714 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
12715 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#lx.\n", hr);
12717 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
12718 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#lx.\n", hr);
12720 memcpy(exec_desc.lpData, quad, sizeof(quad));
12721 ptr = (BYTE *)exec_desc.lpData + sizeof(quad);
12722 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
12723 emit_tquad(&ptr, 0);
12724 emit_end(&ptr);
12726 inst_length = ((BYTE *)ptr - sizeof(quad)) - (BYTE *)exec_desc.lpData;
12728 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
12729 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#lx.\n", hr);
12731 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
12732 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
12733 hr = IDirect3DDevice_BeginScene(device);
12734 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
12735 set_execute_data(execute_buffer, 4, sizeof(quad), inst_length);
12736 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
12737 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#lx.\n", hr);
12738 hr = IDirect3DDevice_EndScene(device);
12739 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
12741 memset(&surface_desc, 0, sizeof(surface_desc));
12742 surface_desc.dwSize = sizeof(surface_desc);
12743 hr = IDirectDrawSurface_Lock(ds, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12744 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12746 for (y = 60; y < 480; y += 120)
12748 for (x = 80; x < 640; x += 160)
12750 ptr = (BYTE *)surface_desc.lpSurface
12751 + y * surface_desc.lPitch
12752 + x * (z_depth == 16 ? 2 : 4);
12753 depth = *((DWORD *)ptr) & z_mask;
12754 expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * z_mask;
12755 max_diff = ((0.5f * 0.9f) / 640.0f) * z_mask;
12756 ok(compare_uint(expected_depth, depth, max_diff),
12757 "z_depth %lu: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
12758 z_depth, depth, expected_depth - depth, expected_depth, max_diff, x, y);
12762 hr = IDirectDrawSurface_Unlock(ds, NULL);
12763 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12765 IDirect3DExecuteBuffer_Release(execute_buffer);
12766 destroy_viewport(device, viewport);
12767 destroy_material(blue_background);
12768 IDirectDrawSurface_Release(ds);
12769 IDirect3DDevice_Release(device);
12770 refcount = IDirectDrawSurface_Release(rt);
12771 ok(!refcount, "Device has %lu references left.\n", refcount);
12772 IDirectDraw_Release(ddraw);
12773 DestroyWindow(window);
12776 static void test_clear(void)
12778 D3DRECT rect_negneg, rect_full = {{0}, {0}, {640}, {480}};
12779 IDirect3DViewport *viewport, *viewport2, *viewport3;
12780 IDirect3DMaterial *white, *red, *green, *blue;
12781 IDirect3DDevice *device;
12782 IDirectDrawSurface *rt;
12783 unsigned int color;
12784 IDirectDraw *ddraw;
12785 D3DRECT rect[2];
12786 ULONG refcount;
12787 HWND window;
12788 HRESULT hr;
12790 window = create_window();
12791 ddraw = create_ddraw();
12792 ok(!!ddraw, "Failed to create a ddraw object.\n");
12793 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
12795 skip("Failed to create a 3D device, skipping test.\n");
12796 IDirectDraw_Release(ddraw);
12797 DestroyWindow(window);
12798 return;
12800 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
12801 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
12803 viewport = create_viewport(device, 0, 0, 640, 480);
12805 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
12806 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
12807 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
12808 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
12810 viewport_set_background(device, viewport, white);
12811 hr = IDirect3DViewport_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
12812 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
12814 /* Positive x, negative y. */
12815 rect[0].x1 = 0;
12816 rect[0].y1 = 480;
12817 rect[0].x2 = 320;
12818 rect[0].y2 = 240;
12820 /* Positive x, positive y. */
12821 rect[1].x1 = 0;
12822 rect[1].y1 = 0;
12823 rect[1].x2 = 320;
12824 rect[1].y2 = 240;
12826 /* Clear 2 rectangles with one call. Unlike d3d8/9, the refrast does not
12827 * refuse negative rectangles, but it will not clear them either. */
12828 viewport_set_background(device, viewport, red);
12829 hr = IDirect3DViewport_Clear(viewport, 2, rect, D3DCLEAR_TARGET);
12830 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
12832 color = get_surface_color(rt, 160, 360);
12833 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 3 (pos, neg) has color 0x%08x.\n", color);
12834 color = get_surface_color(rt, 160, 120);
12835 ok(compare_color(color, 0x00ff0000, 0), "Clear rectangle 1 (pos, pos) has color 0x%08x.\n", color);
12836 color = get_surface_color(rt, 480, 360);
12837 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (NULL) has color 0x%08x.\n", color);
12838 color = get_surface_color(rt, 480, 120);
12839 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (neg, neg) has color 0x%08x.\n", color);
12841 viewport_set_background(device, viewport, white);
12842 hr = IDirect3DViewport_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
12843 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
12845 /* negative x, negative y.
12846 * Also ignored, except on WARP, which clears the entire screen. */
12847 rect_negneg.x1 = 640;
12848 rect_negneg.y1 = 240;
12849 rect_negneg.x2 = 320;
12850 rect_negneg.y2 = 0;
12851 viewport_set_background(device, viewport, green);
12852 hr = IDirect3DViewport_Clear(viewport, 1, &rect_negneg, D3DCLEAR_TARGET);
12853 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
12855 color = get_surface_color(rt, 160, 360);
12856 ok(compare_color(color, 0x00ffffff, 0)
12857 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
12858 "Got unexpected color 0x%08x.\n", color);
12859 color = get_surface_color(rt, 160, 120);
12860 ok(compare_color(color, 0x00ffffff, 0)
12861 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
12862 "Got unexpected color 0x%08x.\n", color);
12863 color = get_surface_color(rt, 480, 360);
12864 ok(compare_color(color, 0x00ffffff, 0)
12865 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
12866 "Got unexpected color 0x%08x.\n", color);
12867 color = get_surface_color(rt, 480, 120);
12868 ok(compare_color(color, 0x00ffffff, 0)
12869 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
12870 "Got unexpected color 0x%08x.\n", color);
12872 /* Test how the viewport affects clears. */
12873 viewport_set_background(device, viewport, white);
12874 hr = IDirect3DViewport_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
12875 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
12877 viewport2 = create_viewport(device, 160, 120, 160, 120);
12878 viewport_set_background(device, viewport2, blue);
12879 hr = IDirect3DViewport_Clear(viewport2, 1, &rect_full, D3DCLEAR_TARGET);
12880 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
12882 viewport3 = create_viewport(device, 320, 240, 320, 240);
12883 viewport_set_background(device, viewport3, green);
12885 rect[0].x1 = 160;
12886 rect[0].y1 = 120;
12887 rect[0].x2 = 480;
12888 rect[0].y2 = 360;
12889 hr = IDirect3DViewport_Clear(viewport3, 1, &rect[0], D3DCLEAR_TARGET);
12890 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
12892 /* AMD drivers do not limit the clear area to the viewport rectangle in
12893 * d3d1. It works as intended on other drivers and on d3d2 and newer on
12894 * AMD cards. */
12895 color = get_surface_color(rt, 158, 118);
12896 ok(compare_color(color, 0x00ffffff, 0)
12897 || broken(ddraw_is_amd(ddraw) && compare_color(color, 0x000000ff, 0)),
12898 "(158, 118) has color 0x%08x.\n", color);
12899 color = get_surface_color(rt, 162, 118);
12900 ok(compare_color(color, 0x00ffffff, 0)
12901 || broken(ddraw_is_amd(ddraw) && compare_color(color, 0x000000ff, 0)),
12902 "(162, 118) has color 0x%08x.\n", color);
12903 color = get_surface_color(rt, 158, 122);
12904 ok(compare_color(color, 0x00ffffff, 0)
12905 || broken(ddraw_is_amd(ddraw) && compare_color(color, 0x000000ff, 0)),
12906 "(158, 122) has color 0x%08x.\n", color);
12907 color = get_surface_color(rt, 162, 122);
12908 ok(compare_color(color, 0x000000ff, 0)
12909 || broken(ddraw_is_amd(ddraw) && compare_color(color, 0x0000ff00, 0)),
12910 "(162, 122) has color 0x%08x.\n", color);
12912 color = get_surface_color(rt, 318, 238);
12913 ok(compare_color(color, 0x000000ff, 0)
12914 || broken(ddraw_is_amd(ddraw) && compare_color(color, 0x0000ff00, 0)),
12915 "(318, 238) has color 0x%08x.\n", color);
12916 color = get_surface_color(rt, 322, 238);
12917 ok(compare_color(color, 0x00ffffff, 0)
12918 || broken(ddraw_is_amd(ddraw) && compare_color(color, 0x0000ff00, 0)),
12919 "(322, 328) has color 0x%08x.\n", color);
12920 color = get_surface_color(rt, 318, 242);
12921 ok(compare_color(color, 0x00ffffff, 0)
12922 || broken(ddraw_is_amd(ddraw) && compare_color(color, 0x0000ff00, 0)),
12923 "(318, 242) has color 0x%08x.\n", color);
12924 color = get_surface_color(rt, 322, 242);
12925 ok(compare_color(color, 0x0000ff00, 0), "(322, 242) has color 0x%08x.\n", color);
12927 color = get_surface_color(rt, 478, 358);
12928 ok(compare_color(color, 0x0000ff00, 0), "(478, 358) has color 0x%08x.\n", color);
12929 color = get_surface_color(rt, 482, 358);
12930 ok(compare_color(color, 0x00ffffff, 0)
12931 || broken(ddraw_is_amd(ddraw) && compare_color(color, 0x000000ff, 0)),
12932 "(482, 358) has color 0x%08x.\n", color);
12933 color = get_surface_color(rt, 478, 362);
12934 ok(compare_color(color, 0x00ffffff, 0)
12935 || broken(ddraw_is_amd(ddraw) && compare_color(color, 0x000000ff, 0)),
12936 "(478, 362) has color 0x%08x.\n", color);
12937 color = get_surface_color(rt, 482, 362);
12938 ok(compare_color(color, 0x00ffffff, 0)
12939 || broken(ddraw_is_amd(ddraw) && compare_color(color, 0x000000ff, 0)),
12940 "(482, 362) has color 0x%08x.\n", color);
12942 /* The clear rectangle is rendertarget absolute, not relative to the
12943 * viewport. */
12944 hr = IDirect3DViewport_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
12945 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
12946 rect[0].x1 = 330;
12947 rect[0].y1 = 250;
12948 rect[0].x2 = 340;
12949 rect[0].y2 = 260;
12950 hr = IDirect3DViewport_Clear(viewport3, 1, &rect[0], D3DCLEAR_TARGET);
12951 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
12953 color = get_surface_color(rt, 328, 248);
12954 ok(compare_color(color, 0x00ffffff, 0), "(328, 248) has color 0x%08x.\n", color);
12955 color = get_surface_color(rt, 332, 248);
12956 ok(compare_color(color, 0x00ffffff, 0), "(332, 248) has color 0x%08x.\n", color);
12957 color = get_surface_color(rt, 328, 252);
12958 ok(compare_color(color, 0x00ffffff, 0), "(328, 252) has color 0x%08x.\n", color);
12959 color = get_surface_color(rt, 332, 252);
12960 ok(compare_color(color, 0x0000ff00, 0), "(332, 252) has color 0x%08x.\n", color);
12962 color = get_surface_color(rt, 338, 248);
12963 ok(compare_color(color, 0x00ffffff, 0), "(338, 248) has color 0x%08x.\n", color);
12964 color = get_surface_color(rt, 342, 248);
12965 ok(compare_color(color, 0x00ffffff, 0), "(342, 248) has color 0x%08x.\n", color);
12966 color = get_surface_color(rt, 338, 252);
12967 ok(compare_color(color, 0x0000ff00, 0), "(338, 252) has color 0x%08x.\n", color);
12968 color = get_surface_color(rt, 342, 252);
12969 ok(compare_color(color, 0x00ffffff, 0), "(342, 252) has color 0x%08x.\n", color);
12971 color = get_surface_color(rt, 328, 258);
12972 ok(compare_color(color, 0x00ffffff, 0), "(328, 258) has color 0x%08x.\n", color);
12973 color = get_surface_color(rt, 332, 258);
12974 ok(compare_color(color, 0x0000ff00, 0), "(332, 258) has color 0x%08x.\n", color);
12975 color = get_surface_color(rt, 328, 262);
12976 ok(compare_color(color, 0x00ffffff, 0), "(328, 262) has color 0x%08x.\n", color);
12977 color = get_surface_color(rt, 332, 262);
12978 ok(compare_color(color, 0x00ffffff, 0), "(332, 262) has color 0x%08x.\n", color);
12980 color = get_surface_color(rt, 338, 258);
12981 ok(compare_color(color, 0x0000ff00, 0), "(338, 258) has color 0x%08x.\n", color);
12982 color = get_surface_color(rt, 342, 258);
12983 ok(compare_color(color, 0x00ffffff, 0), "(342, 258) has color 0x%08x.\n", color);
12984 color = get_surface_color(rt, 338, 262);
12985 ok(compare_color(color, 0x00ffffff, 0), "(338, 262) has color 0x%08x.\n", color);
12986 color = get_surface_color(rt, 342, 262);
12987 ok(compare_color(color, 0x00ffffff, 0), "(342, 262) has color 0x%08x.\n", color);
12989 /* COLORWRITEENABLE, SRGBWRITEENABLE and scissor rectangles do not exist
12990 * in d3d1. */
12992 IDirect3DViewport_Release(viewport3);
12993 IDirect3DViewport_Release(viewport2);
12994 IDirect3DViewport_Release(viewport);
12995 IDirect3DMaterial_Release(white);
12996 IDirect3DMaterial_Release(red);
12997 IDirect3DMaterial_Release(green);
12998 IDirect3DMaterial_Release(blue);
12999 IDirectDrawSurface_Release(rt);
13000 refcount = IDirect3DDevice_Release(device);
13001 ok(!refcount, "Device has %lu references left.\n", refcount);
13002 refcount = IDirectDraw_Release(ddraw);
13003 ok(!refcount, "Ddraw object has %lu references left.\n", refcount);
13004 DestroyWindow(window);
13007 struct enum_surfaces_param
13009 IDirectDraw *ddraw;
13010 DDSURFACEDESC modes[20];
13011 unsigned int mode_count;
13013 IDirectDrawSurface *surfaces[8];
13014 unsigned int count;
13017 static HRESULT CALLBACK build_mode_list_cb(DDSURFACEDESC *desc, void *context)
13019 struct enum_surfaces_param *param = context;
13020 IDirectDrawSurface *surface;
13022 if (SUCCEEDED(IDirectDraw_CreateSurface(param->ddraw, desc, &surface, NULL)))
13024 if (param->mode_count < ARRAY_SIZE(param->modes))
13025 param->modes[param->mode_count] = *desc;
13026 ++param->mode_count;
13027 IDirectDrawSurface_Release(surface);
13030 return DDENUMRET_OK;
13033 static HRESULT WINAPI enum_surfaces_cb(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
13035 struct enum_surfaces_param *param = context;
13036 BOOL found = FALSE;
13037 unsigned int i;
13039 for (i = 0; i < ARRAY_SIZE(param->surfaces); ++i)
13041 if (param->surfaces[i] == surface)
13043 found = TRUE;
13044 break;
13048 ok(found, "Unexpected surface %p enumerated.\n", surface);
13049 IDirectDrawSurface_Release(surface);
13050 ++param->count;
13052 return DDENUMRET_OK;
13055 static HRESULT WINAPI enum_surfaces_create_cb(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
13057 static const DWORD expect_flags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_PIXELFORMAT;
13058 struct enum_surfaces_param *param = context;
13060 ok(!surface, "Unexpected surface %p.\n", surface);
13061 ok((desc->dwFlags & expect_flags) == expect_flags, "Got unexpected flags %#lx.\n", desc->dwFlags);
13062 if (param->count < ARRAY_SIZE(param->modes))
13064 const DDSURFACEDESC *expect = &param->modes[param->count];
13065 ok(desc->dwWidth == expect->dwWidth, "Expected width %lu, got %lu.\n", expect->dwWidth, desc->dwWidth);
13066 ok(desc->dwHeight == expect->dwHeight, "Expected height %lu, got %lu.\n", expect->dwHeight, desc->dwHeight);
13067 ok(!memcmp(&desc->ddpfPixelFormat, &expect->ddpfPixelFormat, sizeof(desc->ddpfPixelFormat)),
13068 "Pixel formats didn't match.\n");
13071 ++param->count;
13073 return DDENUMRET_OK;
13076 static void test_enum_surfaces(void)
13078 struct enum_surfaces_param param = {0};
13079 DDPIXELFORMAT current_format;
13080 IDirectDraw *ddraw;
13081 DDSURFACEDESC desc;
13082 HRESULT hr;
13084 ddraw = create_ddraw();
13085 ok(!!ddraw, "Failed to create a ddraw object.\n");
13086 param.ddraw = ddraw;
13088 memset(&desc, 0, sizeof(desc));
13089 desc.dwSize = sizeof(desc);
13090 hr = IDirectDraw_GetDisplayMode(ddraw, &desc);
13091 ok(hr == DD_OK, "Failed to get display mode, hr %#lx.\n", hr);
13092 current_format = desc.ddpfPixelFormat;
13094 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
13095 ok(hr == DD_OK, "Failed to set cooperative level, hr %#lx.\n", hr);
13097 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_ALL, NULL, NULL, enum_surfaces_cb);
13098 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13100 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_ALL,
13101 NULL, NULL, enum_surfaces_cb);
13102 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13104 memset(&desc, 0, sizeof(desc));
13105 desc.dwSize = sizeof(desc);
13106 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
13107 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
13108 desc.dwMipMapCount = 3;
13109 desc.dwWidth = 32;
13110 desc.dwHeight = 32;
13111 hr = IDirectDraw_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL);
13112 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
13114 hr = IDirectDrawSurface_GetAttachedSurface(param.surfaces[0], &desc.ddsCaps, &param.surfaces[1]);
13115 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#lx.\n", hr);
13116 hr = IDirectDrawSurface_GetAttachedSurface(param.surfaces[1], &desc.ddsCaps, &param.surfaces[2]);
13117 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#lx.\n", hr);
13118 hr = IDirectDrawSurface_GetAttachedSurface(param.surfaces[2], &desc.ddsCaps, &param.surfaces[3]);
13119 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
13120 ok(!param.surfaces[3], "Got unexpected pointer %p.\n", param.surfaces[3]);
13122 param.count = 0;
13123 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
13124 &desc, &param, enum_surfaces_cb);
13125 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#lx.\n", hr);
13126 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13128 param.count = 0;
13129 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
13130 NULL, &param, enum_surfaces_cb);
13131 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#lx.\n", hr);
13132 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13134 desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
13135 param.count = 0;
13136 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
13137 &desc, &param, enum_surfaces_cb);
13138 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
13139 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13141 param.count = 0;
13142 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_NOMATCH,
13143 &desc, &param, enum_surfaces_cb);
13144 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
13145 ok(param.count == 2, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13147 desc.dwFlags = 0;
13148 param.count = 0;
13149 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
13150 &desc, &param, enum_surfaces_cb);
13151 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
13152 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13154 desc.dwFlags = 0;
13155 param.count = 0;
13156 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST, &desc, &param, enum_surfaces_cb);
13157 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
13158 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13160 IDirectDrawSurface_Release(param.surfaces[2]);
13161 IDirectDrawSurface_Release(param.surfaces[1]);
13162 IDirectDrawSurface_Release(param.surfaces[0]);
13164 param.count = 0;
13165 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
13166 NULL, &param, enum_surfaces_cb);
13167 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
13168 ok(!param.count, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13170 memset(&desc, 0, sizeof(desc));
13171 desc.dwSize = sizeof(desc);
13172 desc.dwFlags = DDSD_CAPS;
13173 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
13175 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_ALL,
13176 &desc, &param, enum_surfaces_create_cb);
13177 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#lx.\n", hr);
13179 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_NOMATCH,
13180 &desc, &param, enum_surfaces_create_cb);
13181 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#lx.\n", hr);
13183 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED,
13184 &desc, &param, enum_surfaces_create_cb);
13185 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#lx.\n", hr);
13187 /* When not passed width and height, the callback is called with every
13188 * available display resolution. */
13190 param.mode_count = 0;
13191 desc.dwFlags |= DDSD_PIXELFORMAT;
13192 desc.ddpfPixelFormat = current_format;
13193 hr = IDirectDraw_EnumDisplayModes(ddraw, 0, &desc, &param, build_mode_list_cb);
13194 ok(hr == DD_OK, "Failed to build mode list, hr %#lx.\n", hr);
13196 param.count = 0;
13197 desc.dwFlags &= ~DDSD_PIXELFORMAT;
13198 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
13199 &desc, &param, enum_surfaces_create_cb);
13200 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
13201 ok(param.count == param.mode_count, "Expected %u surfaces, got %u.\n", param.mode_count, param.count);
13203 desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
13204 desc.dwWidth = desc.dwHeight = 32;
13206 param.modes[0].dwWidth = param.modes[0].dwHeight = 32;
13208 param.count = 0;
13209 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
13210 &desc, &param, enum_surfaces_create_cb);
13211 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
13212 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13214 hr = IDirectDraw_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL);
13215 ok(hr == DD_OK, "Failed to create surface, hr %#lx.\n", hr);
13216 param.count = 0;
13217 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
13218 &desc, &param, enum_surfaces_create_cb);
13219 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
13220 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13221 IDirectDrawSurface_Release(param.surfaces[0]);
13223 desc.dwFlags |= DDSD_PIXELFORMAT;
13224 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
13225 desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
13226 desc.ddpfPixelFormat.dwFourCC = 0xdeadbeef;
13228 param.count = 0;
13229 hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
13230 &desc, &param, enum_surfaces_create_cb);
13231 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
13232 ok(!param.count, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13234 IDirectDraw_Release(ddraw);
13237 static void test_execute_data(void)
13239 IDirect3DExecuteBuffer *execute_buffer;
13240 D3DEXECUTEBUFFERDESC exec_desc;
13241 IDirect3DDevice *device;
13242 IDirectDraw *ddraw;
13243 HWND window;
13244 HRESULT hr;
13245 D3DEXECUTEDATA exec_data;
13247 window = create_window();
13248 ddraw = create_ddraw();
13249 ok(!!ddraw, "Failed to create a ddraw object.\n");
13250 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
13252 skip("Failed to create a 3D device, skipping test.\n");
13253 IDirectDraw_Release(ddraw);
13254 DestroyWindow(window);
13255 return;
13258 memset(&exec_desc, 0, sizeof(exec_desc));
13259 exec_desc.dwSize = sizeof(exec_desc);
13260 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
13261 exec_desc.dwBufferSize = 1024;
13262 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
13264 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
13265 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#lx.\n", hr);
13267 memset(&exec_data, 0, sizeof(exec_data));
13269 /* Success case. */
13270 exec_data.dwSize = sizeof(exec_data);
13271 exec_data.dwVertexCount = 3;
13272 exec_data.dwInstructionOffset = 3 * sizeof(D3DVERTEX);
13273 exec_data.dwInstructionLength = 10;
13274 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
13275 ok(SUCCEEDED(hr), "Failed to set execute data, hr %#lx.\n", hr);
13277 /* dwSize is checked against the expected struct size. */
13278 exec_data.dwSize = sizeof(exec_data) - 1;
13279 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
13280 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13281 exec_data.dwSize = sizeof(exec_data) + 1;
13282 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
13283 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13285 /* The rest of the data is not checked for plausibility. */
13286 exec_data.dwSize = sizeof(exec_data);
13287 exec_data.dwVertexCount = 0;
13288 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
13289 ok(SUCCEEDED(hr), "Failed to set execute data, hr %#lx.\n", hr);
13290 exec_data.dwVertexCount = exec_desc.dwBufferSize / sizeof(D3DVERTEX) - 1;
13291 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
13292 ok(SUCCEEDED(hr), "Failed to set execute data, hr %#lx.\n", hr);
13293 exec_data.dwVertexCount = exec_desc.dwBufferSize / sizeof(D3DVERTEX);
13294 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
13295 ok(SUCCEEDED(hr), "Failed to set execute data, hr %#lx.\n", hr);
13296 exec_data.dwVertexCount = exec_desc.dwBufferSize / sizeof(D3DVERTEX) + 1;
13297 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
13298 ok(SUCCEEDED(hr), "Failed to set execute data, hr %#lx.\n", hr);
13299 exec_data.dwVertexCount = 999999;
13300 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
13301 ok(SUCCEEDED(hr), "Failed to set execute data, hr %#lx.\n", hr);
13302 exec_data.dwInstructionOffset = 999999 * sizeof(D3DVERTEX);
13303 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
13304 ok(SUCCEEDED(hr), "Failed to set execute data, hr %#lx.\n", hr);
13305 exec_data.dwInstructionLength = 10240;
13306 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
13307 ok(SUCCEEDED(hr), "Failed to set execute data, hr %#lx.\n", hr);
13309 /* The input structure is not modified. */
13310 ok(exec_data.dwSize == sizeof(exec_data), "Got unexpected struct size %lu.\n",
13311 exec_data.dwSize);
13312 ok(exec_data.dwVertexCount == 999999, "Got unexpected vertex count %lu.\n",
13313 exec_data.dwVertexCount);
13314 ok(exec_data.dwInstructionOffset == 999999 * sizeof(D3DVERTEX), "Got unexpected instruction offset %lu.\n",
13315 exec_data.dwInstructionOffset);
13316 ok(exec_data.dwInstructionLength == 10240, "Got unexpected instruction length %lu.\n",
13317 exec_data.dwInstructionLength);
13319 /* No validation in GetExecuteData. */
13320 memset(&exec_data, 0, sizeof(exec_data));
13321 exec_desc.dwSize = sizeof(exec_desc);
13322 hr = IDirect3DExecuteBuffer_GetExecuteData(execute_buffer, &exec_data);
13323 ok(SUCCEEDED(hr), "Failed to get execute data, hr %#lx.\n", hr);
13325 ok(exec_data.dwSize == sizeof(exec_data), "Got unexpected struct size %lu.\n",
13326 exec_data.dwSize);
13327 ok(exec_data.dwVertexCount == 999999, "Got unexpected vertex count %lu.\n",
13328 exec_data.dwVertexCount);
13329 ok(exec_data.dwInstructionOffset == 999999 * sizeof(D3DVERTEX), "Got unexpected instruction offset %lu.\n",
13330 exec_data.dwInstructionOffset);
13331 ok(exec_data.dwInstructionLength == 10240, "Got unexpected instruction length %lu.\n",
13332 exec_data.dwInstructionLength);
13334 memset(&exec_data, 0xaa, sizeof(exec_data));
13335 exec_desc.dwSize = sizeof(exec_desc) - 1;
13336 hr = IDirect3DExecuteBuffer_GetExecuteData(execute_buffer, &exec_data);
13337 ok(SUCCEEDED(hr), "Failed to get execute data, hr %#lx.\n", hr);
13338 ok(exec_data.dwSize == sizeof(exec_data), "Got unexpected struct size %lu.\n",
13339 exec_data.dwSize);
13340 ok(exec_data.dwVertexCount == 999999, "Got unexpected vertex count %lu.\n",
13341 exec_data.dwVertexCount);
13342 ok(exec_data.dwInstructionOffset == 999999 * sizeof(D3DVERTEX), "Got unexpected instruction offset %lu.\n",
13343 exec_data.dwInstructionOffset);
13344 ok(exec_data.dwInstructionLength == 10240, "Got unexpected instruction length %lu.\n",
13345 exec_data.dwInstructionLength);
13347 exec_desc.dwSize = 0;
13348 hr = IDirect3DExecuteBuffer_GetExecuteData(execute_buffer, &exec_data);
13349 ok(SUCCEEDED(hr), "Failed to get execute data, hr %#lx.\n", hr);
13350 exec_desc.dwSize = sizeof(exec_desc) + 1;
13351 hr = IDirect3DExecuteBuffer_GetExecuteData(execute_buffer, &exec_data);
13352 ok(SUCCEEDED(hr), "Failed to get execute data, hr %#lx.\n", hr);
13353 exec_desc.dwSize = ~0U;
13354 hr = IDirect3DExecuteBuffer_GetExecuteData(execute_buffer, &exec_data);
13355 ok(SUCCEEDED(hr), "Failed to get execute data, hr %#lx.\n", hr);
13357 IDirect3DExecuteBuffer_Release(execute_buffer);
13358 IDirect3DDevice_Release(device);
13359 IDirectDraw_Release(ddraw);
13360 DestroyWindow(window);
13363 static void test_viewport(void)
13365 static struct
13367 D3DVIEWPORT7 vp;
13368 RECT expected_rect;
13369 const char *message;
13371 tests[] =
13373 {{ 0, 0, 640, 480}, { 0, 120, 479, 359}, "(0, 0) - (640, 480) viewport"},
13374 {{ 0, 0, 320, 240}, { 0, 60, 239, 179}, "(0, 0) - (320, 240) viewport"},
13375 {{ 0, 0, 1280, 960}, {-10, -10, -1, -1}, "(0, 0) - (1280, 960) viewport"},
13376 {{ 0, 0, 2000, 1600}, {-10, -10, -1, -1}, "(0, 0) - (2000, 1600) viewport"},
13377 {{100, 100, 640, 480}, {-10, -10, -1, -1}, "(100, 100) - (640, 480) viewport"},
13378 {{ 0, 0, 8192, 8192}, {-10, -10, -1, -1}, "(0, 0) - (8192, 8192) viewport"},
13380 static D3DMATRIX mat =
13382 1.0f, 0.0f, 0.0f, 0.0f,
13383 0.0f, 1.0f, 0.0f, 0.0f,
13384 0.0f, 0.0f, 1.0f, 0.0f,
13385 0.0f, 0.0f, 0.0f, 1.0f,
13387 static D3DLVERTEX quad[] =
13389 {{-1.5f}, {-0.5f}, {0.1f}, 0, {0xffffffff}},
13390 {{-1.5f}, { 0.5f}, {0.1f}, 0, {0xffffffff}},
13391 {{ 0.5f}, {-0.5f}, {0.1f}, 0, {0xffffffff}},
13392 {{ 0.5f}, { 0.5f}, {0.1f}, 0, {0xffffffff}},
13394 D3DMATRIXHANDLE world_handle, view_handle, proj_handle;
13395 IDirect3DViewport *viewport, *full_viewport;
13396 IDirect3DExecuteBuffer *execute_buffer;
13397 IDirect3DMaterial *black_background;
13398 D3DEXECUTEBUFFERDESC exec_desc;
13399 IDirect3DDevice *device;
13400 IDirectDrawSurface *rt;
13401 IDirectDraw *ddraw;
13402 D3DRECT clear_rect;
13403 UINT inst_length;
13404 unsigned int j;
13405 IDirect3D *d3d;
13406 D3DVIEWPORT vp;
13407 ULONG refcount;
13408 HWND window;
13409 HRESULT hr;
13410 void *ptr;
13412 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
13413 0, 0, 640, 480, 0, 0, 0, 0);
13414 ddraw = create_ddraw();
13415 ok(!!ddraw, "Failed to create a ddraw object.\n");
13416 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
13418 skip("Failed to create a 3D device, skipping test.\n");
13419 IDirectDraw_Release(ddraw);
13420 DestroyWindow(window);
13421 return;
13424 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
13425 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
13427 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
13428 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#lx.\n", hr);
13430 black_background = create_diffuse_material(device, 0.0f, 0.0f, 0.0f, 0.0f);
13432 hr = IDirect3DDevice_CreateMatrix(device, &world_handle);
13433 ok(SUCCEEDED(hr), "Creating a matrix object failed, hr %#lx.\n", hr);
13434 hr = IDirect3DDevice_SetMatrix(device, world_handle, &mat);
13435 ok(SUCCEEDED(hr), "Setting a matrix object failed, hr %#lx.\n", hr);
13436 hr = IDirect3DDevice_CreateMatrix(device, &view_handle);
13437 ok(SUCCEEDED(hr), "Creating a matrix object failed, hr %#lx.\n", hr);
13438 hr = IDirect3DDevice_SetMatrix(device, view_handle, &mat);
13439 ok(SUCCEEDED(hr), "Setting a matrix object failed, hr %#lx.\n", hr);
13440 hr = IDirect3DDevice_CreateMatrix(device, &proj_handle);
13441 ok(SUCCEEDED(hr), "Creating a matrix object failed, hr %#lx.\n", hr);
13442 hr = IDirect3DDevice_SetMatrix(device, proj_handle, &mat);
13443 ok(SUCCEEDED(hr), "Setting a matrix object failed, hr %#lx.\n", hr);
13445 memset(&exec_desc, 0, sizeof(exec_desc));
13446 exec_desc.dwSize = sizeof(exec_desc);
13447 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
13448 exec_desc.dwBufferSize = 1024;
13449 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
13451 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
13452 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#lx.\n", hr);
13454 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
13455 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#lx.\n", hr);
13457 memcpy(exec_desc.lpData, quad, sizeof(quad));
13458 ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad);
13459 emit_set_ts(&ptr, D3DTRANSFORMSTATE_WORLD, world_handle);
13460 emit_set_ts(&ptr, D3DTRANSFORMSTATE_VIEW, view_handle);
13461 emit_set_ts(&ptr, D3DTRANSFORMSTATE_PROJECTION, proj_handle);
13462 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, FALSE);
13463 emit_set_rs(&ptr, D3DRENDERSTATE_FOGENABLE, FALSE);
13464 emit_set_rs(&ptr, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
13465 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
13466 emit_tquad(&ptr, 0);
13467 emit_end(&ptr);
13468 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
13469 inst_length -= sizeof(quad);
13471 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
13472 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#lx.\n", hr);
13474 full_viewport = create_viewport(device, 0, 0, 640, 480);
13475 viewport_set_background(device, full_viewport, black_background);
13477 clear_rect.x1 = clear_rect.y1 = 0;
13478 clear_rect.x2 = 640;
13479 clear_rect.y2 = 480;
13481 for (j = 0; j < ARRAY_SIZE(tests); ++j)
13483 winetest_push_context("%s", tests[j].message);
13485 hr = IDirect3DViewport_Clear(full_viewport, 1, &clear_rect, D3DCLEAR_TARGET);
13486 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13488 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
13489 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13490 memset(&vp, 0, sizeof(vp));
13491 vp.dwSize = sizeof(vp);
13492 vp.dwX = tests[j].vp.dwX;
13493 vp.dwY = tests[j].vp.dwY;
13494 vp.dwWidth = tests[j].vp.dwWidth;
13495 vp.dwHeight = tests[j].vp.dwHeight;
13496 vp.dvScaleX = tests[j].vp.dwWidth / 2.0f;
13497 vp.dvScaleY = tests[j].vp.dwHeight / 2.0f;
13498 vp.dvMaxX = 1.0f;
13499 vp.dvMaxY = 1.0f;
13500 vp.dvMinZ = 0.0f;
13501 vp.dvMaxZ = 1.0f;
13502 hr = IDirect3DViewport_SetViewport(viewport, &vp);
13503 ok(hr == D3DERR_VIEWPORTHASNODEVICE, "Got unexpected hr %#lx.\n", hr);
13504 hr = IDirect3DDevice_AddViewport(device, viewport);
13505 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13506 hr = IDirect3DViewport_SetViewport(viewport, &vp);
13507 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13509 hr = IDirect3DDevice_BeginScene(device);
13510 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13512 set_execute_data(execute_buffer, 4, sizeof(quad), inst_length);
13513 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
13514 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13516 hr = IDirect3DDevice_EndScene(device);
13517 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13519 check_rect(rt, tests[j].expected_rect);
13521 destroy_viewport(device, viewport);
13523 winetest_pop_context();
13526 destroy_viewport(device, full_viewport);
13527 IDirectDrawSurface_Release(rt);
13529 IDirect3DExecuteBuffer_Release(execute_buffer);
13530 IDirect3DDevice_DeleteMatrix(device, world_handle);
13531 IDirect3DDevice_DeleteMatrix(device, view_handle);
13532 IDirect3DDevice_DeleteMatrix(device, proj_handle);
13533 destroy_material(black_background);
13534 refcount = IDirect3DDevice_Release(device);
13535 ok(!refcount, "Device has %lu references left.\n", refcount);
13536 IDirect3D2_Release(d3d);
13537 IDirectDraw_Release(ddraw);
13538 DestroyWindow(window);
13541 static void test_find_device(void)
13543 D3DFINDDEVICESEARCH search = {0};
13544 D3DFINDDEVICERESULT result = {0};
13545 IDirect3DDevice *device;
13546 IDirectDraw *ddraw;
13547 IDirect3D *d3d;
13548 unsigned int i;
13549 HWND window;
13550 HRESULT hr;
13552 struct
13554 DWORD size;
13555 GUID guid;
13556 D3DDEVICEDESC_V1 hw_desc;
13557 D3DDEVICEDESC_V1 sw_desc;
13558 } result_v1;
13560 struct
13562 DWORD size;
13563 GUID guid;
13564 D3DDEVICEDESC_V2 hw_desc;
13565 D3DDEVICEDESC_V2 sw_desc;
13566 } result_v2;
13568 static const struct
13570 const GUID *guid;
13571 HRESULT hr;
13573 tests[] =
13575 {&IID_IDirect3D, DDERR_NOTFOUND},
13576 {&IID_IDirect3DRampDevice, D3D_OK},
13577 {&IID_IDirect3DRGBDevice, D3D_OK},
13578 {&IID_IDirect3DMMXDevice, DDERR_NOTFOUND},
13579 {&IID_IDirect3DRefDevice, DDERR_NOTFOUND},
13580 {&IID_IDirect3DTnLHalDevice, DDERR_NOTFOUND},
13581 {&IID_IDirect3DNullDevice, DDERR_NOTFOUND},
13584 ddraw = create_ddraw();
13585 ok(!!ddraw, "Failed to create a ddraw object.\n");
13587 if (FAILED(IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d)))
13589 skip("D3D interface is not available, skipping test.\n");
13590 IDirectDraw_Release(ddraw);
13591 return;
13594 result.dwSize = sizeof(result);
13595 search.dwSize = sizeof(search);
13596 hr = IDirect3D_FindDevice(d3d, NULL, NULL);
13597 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13598 hr = IDirect3D_FindDevice(d3d, NULL, &result);
13599 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13600 hr = IDirect3D_FindDevice(d3d, &search, NULL);
13601 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13602 hr = IDirect3D_FindDevice(d3d, &search, &result);
13603 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13604 ok(result.dwSize == sizeof(result), "Got unexpected result size %lu.\n", result.dwSize);
13605 ok(result.ddHwDesc.dwSize == sizeof(result_v1.hw_desc),
13606 "Got unexpected HW desc size %lu.\n", result.ddHwDesc.dwSize);
13607 ok(result.ddSwDesc.dwSize == sizeof(result_v1.sw_desc),
13608 "Got unexpected SW desc size %lu.\n", result.ddSwDesc.dwSize);
13610 memset(&search, 0, sizeof(search));
13611 memset(&result, 0, sizeof(result));
13612 hr = IDirect3D_FindDevice(d3d, &search, &result);
13613 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13615 search.dwSize = sizeof(search) + 1;
13616 result.dwSize = sizeof(result) + 1;
13617 hr = IDirect3D_FindDevice(d3d, &search, &result);
13618 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13620 search.dwSize = sizeof(search);
13622 memset(&result_v1, 0, sizeof(result_v1));
13623 result_v1.size = sizeof(result_v1);
13624 hr = IDirect3D_FindDevice(d3d, &search, (D3DFINDDEVICERESULT *)&result_v1);
13625 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13626 ok(result_v1.hw_desc.dwSize == sizeof(result_v1.hw_desc),
13627 "Got unexpected HW desc size %lu.\n", result_v1.hw_desc.dwSize);
13628 ok(result_v1.sw_desc.dwSize == sizeof(result_v1.sw_desc),
13629 "Got unexpected SW desc size %lu.\n", result_v1.sw_desc.dwSize);
13631 memset(&result_v2, 0, sizeof(result_v2));
13632 result_v2.size = sizeof(result_v2);
13633 hr = IDirect3D_FindDevice(d3d, &search, (D3DFINDDEVICERESULT *)&result_v2);
13634 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13635 ok(result_v2.hw_desc.dwSize == sizeof(result_v1.hw_desc),
13636 "Got unexpected HW desc size %lu.\n", result_v2.hw_desc.dwSize);
13637 ok(result_v2.sw_desc.dwSize == sizeof(result_v1.sw_desc),
13638 "Got unexpected SW desc size %lu.\n", result_v2.sw_desc.dwSize);
13640 for (i = 0; i < ARRAY_SIZE(tests); ++i)
13642 memset(&search, 0, sizeof(search));
13643 search.dwSize = sizeof(search);
13644 search.dwFlags = D3DFDS_GUID;
13645 search.guid = *tests[i].guid;
13647 memset(&result, 0, sizeof(result));
13648 result.dwSize = sizeof(result);
13650 hr = IDirect3D_FindDevice(d3d, &search, &result);
13651 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#lx.\n", i, hr);
13652 ok(result.dwSize == sizeof(result), "Test %u: Got unexpected result size %lu.\n", i, result.dwSize);
13653 if (SUCCEEDED(hr))
13655 ok(result.ddHwDesc.dwSize == sizeof(result_v1.hw_desc),
13656 "Test %u: Got unexpected HW desc size %lu.\n", i, result.ddHwDesc.dwSize);
13657 ok(result.ddSwDesc.dwSize == sizeof(result_v1.sw_desc),
13658 "Test %u: Got unexpected SW desc size %lu.\n", i, result.ddSwDesc.dwSize);
13660 else
13662 ok(!result.ddHwDesc.dwSize,
13663 "Test %u: Got unexpected HW desc size %lu.\n", i, result.ddHwDesc.dwSize);
13664 ok(!result.ddSwDesc.dwSize,
13665 "Test %u: Got unexpected SW desc size %lu.\n", i, result.ddSwDesc.dwSize);
13669 /* The HAL device can only be enumerated if hardware acceleration is present. */
13670 search.dwSize = sizeof(search);
13671 search.dwFlags = D3DFDS_GUID;
13672 search.guid = IID_IDirect3DHALDevice;
13673 result.dwSize = sizeof(result);
13674 hr = IDirect3D_FindDevice(d3d, &search, &result);
13676 window = create_window();
13677 device = create_device(ddraw, window, DDSCL_NORMAL);
13678 if (hr == D3D_OK)
13679 ok(!!device, "Failed to create a 3D device.\n");
13680 else
13681 ok(!device, "Succeeded to create a 3D device.\n");
13682 if (device)
13683 IDirect3DDevice_Release(device);
13684 DestroyWindow(window);
13686 /* Curiously the colour model criteria seem to be ignored. */
13687 search.dwSize = sizeof(search);
13688 search.dwFlags = D3DFDS_COLORMODEL;
13689 search.dcmColorModel = 0xdeadbeef;
13690 result.dwSize = sizeof(result);
13691 hr = IDirect3D_FindDevice(d3d, &search, &result);
13692 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13694 IDirect3D_Release(d3d);
13695 IDirectDraw_Release(ddraw);
13698 static IDirectDraw *killfocus_ddraw;
13699 static IDirectDrawSurface *killfocus_surface;
13701 static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
13703 ULONG ref;
13705 if (message == WM_KILLFOCUS)
13707 ref = IDirectDrawSurface_Release(killfocus_surface);
13708 ok(!ref, "Unexpected surface refcount %lu.\n", ref);
13709 ref = IDirectDraw_Release(killfocus_ddraw);
13710 ok(!ref, "Unexpected ddraw refcount %lu.\n", ref);
13711 killfocus_ddraw = NULL;
13714 return DefWindowProcA(window, message, wparam, lparam);
13717 static void test_killfocus(void)
13719 DDSURFACEDESC surface_desc;
13720 HRESULT hr;
13721 HWND window;
13722 WNDCLASSA wc = {0};
13724 wc.lpfnWndProc = killfocus_proc;
13725 wc.lpszClassName = "ddraw_killfocus_wndproc_wc";
13726 ok(RegisterClassA(&wc), "Failed to register window class.\n");
13728 window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
13729 0, 0, 640, 480, 0, 0, 0, 0);
13731 killfocus_ddraw = create_ddraw();
13732 ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n");
13734 hr = IDirectDraw_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
13735 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
13737 memset(&surface_desc, 0, sizeof(surface_desc));
13738 surface_desc.dwSize = sizeof(surface_desc);
13739 surface_desc.dwFlags = DDSD_CAPS;
13740 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
13741 hr = IDirectDraw_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL);
13742 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
13744 SetForegroundWindow(GetDesktopWindow());
13745 ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n");
13747 DestroyWindow(window);
13748 UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
13751 static void test_gdi_surface(void)
13753 IDirectDrawSurface *primary, *backbuffer, *gdi_surface;
13754 DDSCAPS caps = {DDSCAPS_BACKBUFFER};
13755 DDSURFACEDESC surface_desc;
13756 IDirectDraw *ddraw;
13757 ULONG refcount;
13758 HWND window;
13759 HRESULT hr;
13761 window = create_window();
13762 ddraw = create_ddraw();
13763 ok(!!ddraw, "Failed to create a ddraw object.\n");
13764 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13765 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13767 /* Retrieving the GDI surface requires a primary surface to exist. */
13768 gdi_surface = (void *)0xc0dec0de;
13769 hr = IDirectDraw_GetGDISurface(ddraw, &gdi_surface);
13770 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
13771 ok(!gdi_surface, "Got unexpected surface %p.\n", gdi_surface);
13773 hr = IDirectDraw_FlipToGDISurface(ddraw);
13774 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
13776 memset(&surface_desc, 0, sizeof(surface_desc));
13777 surface_desc.dwSize = sizeof(surface_desc);
13778 surface_desc.dwFlags = DDSD_CAPS;
13779 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
13780 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
13781 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13783 hr = IDirectDraw_GetGDISurface(ddraw, &gdi_surface);
13784 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13785 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
13786 IDirectDrawSurface_Release(gdi_surface);
13788 /* Flipping to the GDI surface requires the primary surface to be
13789 * flippable. */
13790 hr = IDirectDraw_FlipToGDISurface(ddraw);
13791 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#lx.\n", hr);
13793 IDirectDrawSurface_Release(primary);
13795 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
13796 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13798 memset(&surface_desc, 0, sizeof(surface_desc));
13799 surface_desc.dwSize = sizeof(surface_desc);
13800 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
13801 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
13802 surface_desc.dwBackBufferCount = 1;
13803 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
13804 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13805 hr = IDirectDrawSurface_GetAttachedSurface(primary, &caps, &backbuffer);
13806 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13807 ok(backbuffer != primary, "Got unexpected backbuffer %p.\n", backbuffer);
13809 hr = IDirectDraw_GetGDISurface(ddraw, &gdi_surface);
13810 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13811 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
13812 IDirectDrawSurface_Release(gdi_surface);
13814 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
13815 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13816 hr = IDirectDraw_GetGDISurface(ddraw, &gdi_surface);
13817 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13818 ok(gdi_surface == backbuffer || broken(gdi_surface == primary),
13819 "Got unexpected surface %p, expected %p.\n", gdi_surface, backbuffer);
13820 IDirectDrawSurface_Release(gdi_surface);
13822 hr = IDirectDraw_FlipToGDISurface(ddraw);
13823 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13825 hr = IDirectDraw_GetGDISurface(ddraw, &gdi_surface);
13826 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13827 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
13828 IDirectDrawSurface_Release(gdi_surface);
13830 hr = IDirectDraw_FlipToGDISurface(ddraw);
13831 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13833 IDirectDrawSurface_Release(backbuffer);
13834 IDirectDrawSurface_Release(primary);
13836 refcount = IDirectDraw_Release(ddraw);
13837 ok(!refcount, "%lu references left.\n", refcount);
13838 DestroyWindow(window);
13841 static void test_alphatest(void)
13843 #define ALPHATEST_PASSED 0x0000ff00
13844 #define ALPHATEST_FAILED 0x00ff0000
13845 D3DRECT rect_full = {{0}, {0}, {640}, {480}};
13846 IDirect3DExecuteBuffer *execute_buffer;
13847 IDirect3DMaterial *blue, *failed;
13848 D3DEXECUTEBUFFERDESC exec_desc;
13849 IDirect3DViewport *viewport;
13850 IDirect3DDevice *device;
13851 IDirectDrawSurface *rt;
13852 unsigned int color, i;
13853 IDirectDraw *ddraw;
13854 UINT inst_length;
13855 ULONG refcount;
13856 HWND window;
13857 HRESULT hr;
13858 void *ptr;
13860 static const struct
13862 D3DCMPFUNC func;
13863 unsigned int color_less, color_equal, color_greater;
13865 test_data[] =
13867 {D3DCMP_NEVER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED},
13868 {D3DCMP_LESS, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED},
13869 {D3DCMP_EQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED},
13870 {D3DCMP_LESSEQUAL, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_FAILED},
13871 {D3DCMP_GREATER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_PASSED},
13872 {D3DCMP_NOTEQUAL, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED},
13873 {D3DCMP_GREATEREQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED},
13874 {D3DCMP_ALWAYS, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
13876 static D3DLVERTEX quad[] =
13878 {{-1.0f}, {-1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
13879 {{-1.0f}, { 1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
13880 {{ 1.0f}, {-1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
13881 {{ 1.0f}, { 1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
13884 window = create_window();
13885 ddraw = create_ddraw();
13886 ok(!!ddraw, "Failed to create a ddraw object.\n");
13887 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
13889 skip("Failed to create a 3D device.\n");
13890 IDirectDraw_Release(ddraw);
13891 DestroyWindow(window);
13892 return;
13894 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
13895 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13897 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
13898 failed = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
13900 viewport = create_viewport(device, 0, 0, 640, 480);
13902 viewport_set_background(device, viewport, blue);
13903 hr = IDirect3DViewport_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
13904 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13906 memset(&exec_desc, 0, sizeof(exec_desc));
13907 exec_desc.dwSize = sizeof(exec_desc);
13908 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
13909 exec_desc.dwBufferSize = 1024;
13910 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
13912 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
13913 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13915 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
13916 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13918 ptr = exec_desc.lpData;
13919 emit_set_rs(&ptr, D3DRENDERSTATE_LIGHTING, FALSE);
13920 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, FALSE);
13921 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
13922 emit_end(&ptr);
13923 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
13925 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
13926 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13928 set_execute_data(execute_buffer, 0, 0, inst_length);
13929 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
13930 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13932 viewport_set_background(device, viewport, failed);
13933 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
13935 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
13936 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13938 memcpy(exec_desc.lpData, quad, sizeof(quad));
13939 ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad);
13940 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHAFUNC, test_data[i].func);
13941 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHAREF, 0x70);
13942 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, ARRAY_SIZE(quad));
13943 emit_tquad(&ptr, 0);
13944 emit_end(&ptr);
13945 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
13946 inst_length -= sizeof(quad);
13948 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
13949 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13951 hr = IDirect3DViewport_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
13952 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13953 hr = IDirect3DDevice_BeginScene(device);
13954 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13955 set_execute_data(execute_buffer, ARRAY_SIZE(quad), sizeof(quad), inst_length);
13956 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
13957 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13958 hr = IDirect3DDevice_EndScene(device);
13959 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13960 color = get_surface_color(rt, 320, 240);
13961 ok(compare_color(color, test_data[i].color_greater, 0),
13962 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
13963 color, test_data[i].color_greater, test_data[i].func);
13965 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
13966 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13968 memcpy(exec_desc.lpData, quad, sizeof(quad));
13969 ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad);
13970 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHAREF, 0xff70);
13971 emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, ARRAY_SIZE(quad));
13972 emit_tquad(&ptr, 0);
13973 emit_end(&ptr);
13974 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
13975 inst_length -= sizeof(quad);
13977 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
13978 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13980 hr = IDirect3DViewport_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
13981 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13982 hr = IDirect3DDevice_BeginScene(device);
13983 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13984 set_execute_data(execute_buffer, ARRAY_SIZE(quad), sizeof(quad), inst_length);
13985 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
13986 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13987 hr = IDirect3DDevice_EndScene(device);
13988 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13989 color = get_surface_color(rt, 320, 240);
13990 ok(compare_color(color, test_data[i].color_greater, 0),
13991 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
13992 color, test_data[i].color_greater, test_data[i].func);
13995 IDirect3DExecuteBuffer_Release(execute_buffer);
13996 destroy_viewport(device, viewport);
13997 destroy_material(failed);
13998 destroy_material(blue);
13999 IDirectDrawSurface_Release(rt);
14000 refcount = IDirect3DDevice_Release(device);
14001 ok(!refcount, "Device has %lu references left.\n", refcount);
14002 refcount = IDirectDraw_Release(ddraw);
14003 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
14004 DestroyWindow(window);
14007 static void test_clipper_refcount(void)
14009 IDirectDrawSurface *surface;
14010 IDirectDrawClipper *clipper, *clipper2;
14011 DDSURFACEDESC surface_desc;
14012 IDirectDraw *ddraw;
14013 ULONG refcount;
14014 HWND window;
14015 HRESULT hr;
14016 BOOL changed;
14017 const IDirectDrawClipperVtbl *orig_vtbl;
14019 window = create_window();
14020 ddraw = create_ddraw();
14021 ok(!!ddraw, "Failed to create a ddraw object.\n");
14022 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
14023 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14025 memset(&surface_desc, 0, sizeof(surface_desc));
14026 surface_desc.dwSize = sizeof(surface_desc);
14027 surface_desc.dwFlags = DDSD_CAPS;
14028 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
14029 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14030 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14032 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
14033 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
14034 refcount = get_refcount((IUnknown *)clipper);
14035 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
14037 /* Show that clipper validation doesn't somehow happen through per-clipper vtable
14038 * pointers. */
14039 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper2, NULL);
14040 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
14041 ok(clipper->lpVtbl == clipper2->lpVtbl, "Got different clipper vtables %p and %p.\n",
14042 clipper->lpVtbl, clipper2->lpVtbl);
14043 orig_vtbl = clipper->lpVtbl;
14044 IDirectDrawClipper_Release(clipper2);
14046 /* Surfaces hold a reference to clippers. No surprises there. */
14047 hr = IDirectDrawSurface_SetClipper(surface, clipper);
14048 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
14049 refcount = get_refcount((IUnknown *)clipper);
14050 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
14052 hr = IDirectDrawSurface_GetClipper(surface, &clipper2);
14053 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#lx.\n", hr);
14054 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
14055 refcount = IDirectDrawClipper_Release(clipper2);
14056 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
14058 hr = IDirectDrawSurface_SetClipper(surface, NULL);
14059 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
14060 refcount = get_refcount((IUnknown *)clipper);
14061 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
14063 hr = IDirectDrawSurface_SetClipper(surface, clipper);
14064 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
14065 refcount = get_refcount((IUnknown *)clipper);
14066 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
14068 refcount = IDirectDrawSurface_Release(surface);
14069 ok(!refcount, "%lu references left.\n", refcount);
14070 refcount = get_refcount((IUnknown *)clipper);
14071 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
14073 /* SetClipper with an invalid pointer crashes. */
14075 /* Clipper methods work with a broken vtable, with the exception of Release. */
14076 clipper->lpVtbl = (void *)0xdeadbeef;
14077 refcount = orig_vtbl->AddRef(clipper);
14078 todo_wine ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
14079 refcount = orig_vtbl->Release(clipper);
14080 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
14082 clipper->lpVtbl = orig_vtbl;
14083 refcount = orig_vtbl->Release(clipper);
14084 todo_wine ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
14086 /* Fix the refcount difference because Wine did not increase the ref in the
14087 * AddRef call above. */
14088 if (refcount)
14090 refcount = IDirectDrawClipper_Release(clipper);
14091 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
14094 /* Steal the reference and see what happens - releasing the surface works fine.
14095 * The clipper is destroyed and not kept alive by a hidden refcount - trying to
14096 * release it after the GetClipper call is likely to crash, and certain to crash
14097 * if we allocate and zero as much heap memory as we can get. */
14098 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14099 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14100 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
14101 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
14102 hr = IDirectDrawSurface_SetClipper(surface, clipper);
14103 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
14105 IDirectDrawClipper_Release(clipper);
14106 IDirectDrawClipper_Release(clipper);
14108 if (0)
14110 /* Disabled because it causes heap corruption (HeapValidate fails and random
14111 * hangs in a later HeapFree) on Windows on one of my Machines: MacbookPro 10,1
14112 * running Windows 10 18363.535 and Nvidia driver 425.31. Driver version 441.66
14113 * is affected too. Some testbot machines have crashes directly in GetClipper
14114 * or proceed with a corrupted heap too.
14116 * The same Windows and driver versions run the test without heap corruption on
14117 * a Geforce 1060 GTX card. I have not seen the problem on AMD GPUs either. */
14118 hr = IDirectDrawSurface_GetClipper(surface, &clipper2);
14119 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#lx.\n", hr);
14120 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
14123 /* Show that invoking the Release method does not crash, but don't get the
14124 * vtable through the clipper pointer because it is no longer pointing to
14125 * valid memory. */
14126 refcount = orig_vtbl->Release(clipper);
14127 ok(!refcount, "%lu references left.\n", refcount);
14129 refcount = IDirectDrawSurface_Release(surface);
14130 ok(!refcount, "%lu references left.\n", refcount);
14132 /* It looks like the protection against invalid thispointers is part of
14133 * the IDirectDrawClipper method implementation, not IDirectDrawSurface. */
14134 clipper = calloc(1, 0x1000);
14135 ok(!!clipper, "failed to allocate memory\n");
14137 /* Assigning the vtable to our fake clipper does NOT make a difference on
14138 * native - there is a different member of the clipper implementation struct
14139 * that is used to determine if a clipper is valid. */
14140 clipper->lpVtbl = orig_vtbl;
14142 refcount = orig_vtbl->AddRef(clipper);
14143 todo_wine ok(!refcount, "Got refcount %lu.\n", refcount);
14144 refcount = orig_vtbl->AddRef((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef);
14145 ok(!refcount, "Got refcount %lu.\n", refcount);
14147 changed = 0x1234;
14148 hr = orig_vtbl->IsClipListChanged(clipper, &changed);
14149 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
14150 todo_wine ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
14152 changed = 0x1234;
14153 hr = orig_vtbl->IsClipListChanged((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef, &changed);
14154 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
14155 ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
14157 /* Nope, we can't initialize our fake clipper. */
14158 hr = orig_vtbl->Initialize(clipper, ddraw, 0);
14159 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
14161 free(clipper);
14163 refcount = IDirectDraw_Release(ddraw);
14164 ok(!refcount, "%lu references left.\n", refcount);
14165 DestroyWindow(window);
14168 static void test_caps(void)
14170 DWORD caps_never, caps_always, caps_hal;
14171 DDCAPS hal_caps, hel_caps;
14172 IDirectDraw *ddraw;
14173 HRESULT hr;
14174 BOOL no3d;
14176 caps_never = DDSCAPS_RESERVED1
14177 | DDSCAPS_ALPHA
14178 | DDSCAPS_PRIMARYSURFACELEFT
14179 | DDSCAPS_SYSTEMMEMORY
14180 | DDSCAPS_VISIBLE
14181 | DDSCAPS_WRITEONLY
14182 | DDSCAPS_LIVEVIDEO
14183 | DDSCAPS_HWCODEC
14184 | DDSCAPS_MODEX
14185 | DDSCAPS_RESERVED2
14186 | 0x01000000u
14187 | 0x02000000u
14188 | DDSCAPS_ALLOCONLOAD
14189 | DDSCAPS_VIDEOPORT
14190 | DDSCAPS_STANDARDVGAMODE
14191 | DDSCAPS_OPTIMIZED;
14193 caps_always = DDSCAPS_FLIP
14194 | DDSCAPS_OFFSCREENPLAIN
14195 | DDSCAPS_PRIMARYSURFACE
14196 | DDSCAPS_TEXTURE
14197 | DDSCAPS_ZBUFFER
14198 | DDSCAPS_MIPMAP;
14200 caps_hal = DDSCAPS_BACKBUFFER
14201 | DDSCAPS_COMPLEX
14202 | DDSCAPS_FRONTBUFFER
14203 | DDSCAPS_3DDEVICE
14204 | DDSCAPS_VIDEOMEMORY
14205 | DDSCAPS_LOCALVIDMEM
14206 | DDSCAPS_NONLOCALVIDMEM;
14208 ddraw = create_ddraw();
14209 ok(!!ddraw, "Failed to create a ddraw object.\n");
14211 memset(&hal_caps, 0, sizeof(hal_caps));
14212 memset(&hel_caps, 0, sizeof(hel_caps));
14213 hal_caps.dwSize = sizeof(hal_caps);
14214 hel_caps.dwSize = sizeof(hel_caps);
14215 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, &hel_caps);
14216 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14217 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
14218 "Got unexpected caps %#lx, expected %#lx.\n",
14219 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
14220 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
14221 "Got unexpected caps %#lx, expected %#lx.\n",
14222 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
14224 no3d = !(hal_caps.ddsCaps.dwCaps & DDSCAPS_3DDEVICE);
14225 if (hal_caps.ddsCaps.dwCaps)
14227 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
14228 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
14229 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
14230 "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
14232 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
14233 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
14234 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
14235 "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
14237 IDirectDraw_Release(ddraw);
14239 if (hal_caps.ddsCaps.dwCaps)
14241 hr = DirectDrawCreate((GUID *)DDCREATE_HARDWAREONLY, &ddraw, NULL);
14242 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14244 memset(&hal_caps, 0, sizeof(hal_caps));
14245 memset(&hel_caps, 0, sizeof(hel_caps));
14246 hal_caps.dwSize = sizeof(hal_caps);
14247 hel_caps.dwSize = sizeof(hel_caps);
14248 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, &hel_caps);
14249 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14250 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
14251 "Got unexpected caps %#lx, expected %#lx.\n",
14252 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
14253 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
14254 "Got unexpected caps %#lx, expected %#lx.\n",
14255 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
14257 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
14258 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
14259 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
14260 "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
14261 if (is_ddraw64)
14263 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
14264 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
14265 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
14266 "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
14268 else
14270 todo_wine ok(!hel_caps.ddsCaps.dwCaps, "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
14273 IDirectDraw_Release(ddraw);
14276 hr = DirectDrawCreate((GUID *)DDCREATE_EMULATIONONLY, &ddraw, NULL);
14277 ok(hr == DD_OK || (is_ddraw64 && hr == E_FAIL), "Got unexpected hr %#lx.\n", hr);
14278 if (SUCCEEDED(hr))
14280 memset(&hal_caps, 0, sizeof(hal_caps));
14281 memset(&hel_caps, 0, sizeof(hel_caps));
14282 hal_caps.dwSize = sizeof(hal_caps);
14283 hel_caps.dwSize = sizeof(hel_caps);
14284 hr = IDirectDraw_GetCaps(ddraw, &hal_caps, &hel_caps);
14285 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14286 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
14287 "Got unexpected caps %#lx, expected %#lx.\n",
14288 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
14289 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
14290 "Got unexpected caps %#lx, expected %#lx.\n",
14291 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
14293 todo_wine ok(!hal_caps.ddsCaps.dwCaps, "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
14294 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
14295 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
14296 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
14297 "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
14299 IDirectDraw_Release(ddraw);
14303 static void test_d32_support(void)
14305 IDirectDrawSurface *surface;
14306 DDSURFACEDESC surface_desc;
14307 IDirectDraw *ddraw;
14308 ULONG refcount;
14309 HWND window;
14310 HRESULT hr;
14312 window = create_window();
14313 ddraw = create_ddraw();
14314 ok(!!ddraw, "Failed to create a ddraw object.\n");
14315 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
14316 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14318 memset(&surface_desc, 0, sizeof(surface_desc));
14319 surface_desc.dwSize = sizeof(surface_desc);
14320 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
14321 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
14322 surface_desc.dwZBufferBitDepth = 32;
14323 surface_desc.dwWidth = 64;
14324 surface_desc.dwHeight = 64;
14325 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14326 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14328 memset(&surface_desc, 0, sizeof(surface_desc));
14329 surface_desc.dwSize = sizeof(surface_desc);
14330 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
14331 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14332 ok((surface_desc.dwFlags & DDSD_ZBUFFERBITDEPTH), "Got unexpected flags %#lx.\n", surface_desc.dwFlags);
14333 ok(surface_desc.dwZBufferBitDepth == 32,
14334 "Got unexpected dwZBufferBitDepth %lu.\n", surface_desc.dwZBufferBitDepth);
14335 ok(!(surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY),
14336 "Got unexpected surface caps %#lx.\n", surface_desc.ddsCaps.dwCaps);
14337 IDirectDrawSurface_Release(surface);
14339 refcount = IDirectDraw_Release(ddraw);
14340 ok(!refcount, "%lu references left.\n", refcount);
14341 DestroyWindow(window);
14344 struct find_different_mode_param
14346 unsigned int old_width;
14347 unsigned int old_height;
14348 unsigned int new_width;
14349 unsigned int new_height;
14352 static HRESULT CALLBACK find_different_mode_callback(DDSURFACEDESC *surface_desc, void *context)
14354 struct find_different_mode_param *param = context;
14356 if (surface_desc->ddpfPixelFormat.dwRGBBitCount != registry_mode.dmBitsPerPel)
14357 return DDENUMRET_OK;
14359 if (surface_desc->dwWidth != param->old_width && surface_desc->dwHeight != param->old_height)
14361 /* See test_coop_level_mode_set_enum_cb() for why enumeration might accidentally continue. */
14362 if (!param->new_width || (param->new_width < registry_mode.dmPelsWidth
14363 && param->new_height < registry_mode.dmPelsHeight))
14365 param->new_width = surface_desc->dwWidth;
14366 param->new_height = surface_desc->dwHeight;
14368 return DDENUMRET_CANCEL;
14371 return DDENUMRET_OK;
14374 static void test_cursor_clipping(void)
14376 struct find_different_mode_param param;
14377 DDSURFACEDESC surface_desc;
14378 RECT rect, clip_rect;
14379 IDirectDraw *ddraw;
14380 HWND window;
14381 HRESULT hr;
14382 BOOL ret;
14384 window = create_window();
14385 ok(!!window, "Failed to create a window.\n");
14386 ddraw = create_ddraw();
14387 ok(!!ddraw, "Failed to create a ddraw object.\n");
14389 memset(&surface_desc, 0, sizeof(surface_desc));
14390 surface_desc.dwSize = sizeof(surface_desc);
14391 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
14392 ok(hr == DD_OK, "GetDisplayMode failed, hr %#lx.\n", hr);
14394 memset(&param, 0, sizeof(param));
14395 param.old_width = surface_desc.dwWidth;
14396 param.old_height = surface_desc.dwHeight;
14397 hr = IDirectDraw_EnumDisplayModes(ddraw, 0, NULL, &param, find_different_mode_callback);
14398 ok(hr == DD_OK, "EnumDisplayModes failed, hr %#lx.\n", hr);
14399 if (!(param.new_width && param.new_height))
14401 skip("Failed to find a different mode than %ux%u.\n", param.old_width, param.old_height);
14402 goto done;
14405 ret = ClipCursor(NULL);
14406 ok(ret, "ClipCursor failed, error %lu.\n", GetLastError());
14407 get_virtual_rect(&rect);
14408 ret = GetClipCursor(&clip_rect);
14409 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
14410 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
14411 wine_dbgstr_rect(&clip_rect));
14413 /* Set cooperative level to normal */
14414 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
14415 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
14416 flush_events();
14417 get_virtual_rect(&rect);
14418 ret = GetClipCursor(&clip_rect);
14419 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
14420 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
14421 wine_dbgstr_rect(&clip_rect));
14423 hr = set_display_mode(ddraw, param.new_width, param.new_height);
14424 ok(hr == DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode failed, hr %#lx.\n", hr);
14425 if (FAILED(hr))
14427 win_skip("SetDisplayMode failed, hr %#lx.\n", hr);
14428 goto done;
14430 flush_events();
14431 get_virtual_rect(&rect);
14432 ret = GetClipCursor(&clip_rect);
14433 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
14434 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
14435 wine_dbgstr_rect(&clip_rect));
14437 hr = IDirectDraw_RestoreDisplayMode(ddraw);
14438 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#lx.\n", hr);
14439 flush_events();
14440 get_virtual_rect(&rect);
14441 ret = GetClipCursor(&clip_rect);
14442 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
14443 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
14444 wine_dbgstr_rect(&clip_rect));
14446 /* Switch to full screen cooperative level */
14447 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
14448 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
14449 flush_events();
14450 SetRect(&rect, 0, 0, param.old_width, param.old_height);
14451 ret = GetClipCursor(&clip_rect);
14452 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
14453 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
14454 wine_dbgstr_rect(&clip_rect));
14456 hr = set_display_mode(ddraw, param.new_width, param.new_height);
14457 ok(hr == DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode failed, hr %#lx.\n", hr);
14458 if (FAILED(hr))
14460 win_skip("SetDisplayMode failed, hr %#lx.\n", hr);
14461 goto done;
14463 flush_events();
14464 SetRect(&rect, 0, 0, param.new_width, param.new_height);
14465 ret = GetClipCursor(&clip_rect);
14466 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
14467 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
14468 wine_dbgstr_rect(&clip_rect));
14470 /* Restore display mode */
14471 hr = IDirectDraw_RestoreDisplayMode(ddraw);
14472 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#lx.\n", hr);
14473 flush_events();
14474 SetRect(&rect, 0, 0, param.old_width, param.old_height);
14475 ret = GetClipCursor(&clip_rect);
14476 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
14477 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
14478 wine_dbgstr_rect(&clip_rect));
14480 /* Switch to normal cooperative level */
14481 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
14482 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
14483 flush_events();
14484 get_virtual_rect(&rect);
14485 ret = GetClipCursor(&clip_rect);
14486 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
14487 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
14488 wine_dbgstr_rect(&clip_rect));
14490 done:
14491 IDirectDraw_Release(ddraw);
14492 DestroyWindow(window);
14495 static void check_vtbl_protection_(int line, const void *vtbl)
14497 MEMORY_BASIC_INFORMATION info;
14498 SIZE_T ret = VirtualQuery(vtbl, &info, sizeof(info));
14499 ok_(__FILE__, line)(ret == sizeof(info), "Failed to query memory.\n");
14500 ok_(__FILE__, line)(info.Protect & (PAGE_READWRITE | PAGE_WRITECOPY), "Got protection %#lx.\n", info.Protect);
14502 #define check_vtbl_protection(a) check_vtbl_protection_(__LINE__, a)
14504 static void test_vtbl_protection(void)
14506 PALETTEENTRY palette_entries[256];
14507 IDirectDrawSurface7 *surface7;
14508 IDirectDrawSurface4 *surface4;
14509 IDirectDrawSurface3 *surface3;
14510 IDirectDrawSurface2 *surface2;
14511 IDirectDrawSurface *surface1;
14512 IDirectDrawPalette *palette;
14513 DDSURFACEDESC surface_desc;
14514 IDirectDraw *ddraw;
14515 ULONG refcount;
14516 HWND window;
14517 HRESULT hr;
14519 window = create_window();
14520 ddraw = create_ddraw();
14521 ok(!!ddraw, "Failed to create a ddraw object.\n");
14522 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
14523 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14525 memset(&surface_desc, 0, sizeof(surface_desc));
14526 surface_desc.dwSize = sizeof(surface_desc);
14527 surface_desc.dwFlags = DDSD_CAPS;
14528 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
14529 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
14530 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14531 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface2);
14532 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14533 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface3, (void **)&surface3);
14534 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14535 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface4, (void **)&surface4);
14536 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14537 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface7, (void **)&surface7);
14538 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14540 memset(palette_entries, 0, sizeof(palette_entries));
14541 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
14542 palette_entries, &palette, NULL);
14543 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14545 check_vtbl_protection(ddraw->lpVtbl);
14546 check_vtbl_protection(palette->lpVtbl);
14547 check_vtbl_protection(surface1->lpVtbl);
14548 check_vtbl_protection(surface2->lpVtbl);
14549 check_vtbl_protection(surface3->lpVtbl);
14550 check_vtbl_protection(surface4->lpVtbl);
14551 check_vtbl_protection(surface7->lpVtbl);
14553 IDirectDrawPalette_Release(palette);
14554 IDirectDrawSurface_Release(surface1);
14555 IDirectDrawSurface2_Release(surface2);
14556 IDirectDrawSurface3_Release(surface3);
14557 IDirectDrawSurface4_Release(surface4);
14558 IDirectDrawSurface7_Release(surface7);
14559 refcount = IDirectDraw_Release(ddraw);
14560 ok(!refcount, "%lu references left.\n", refcount);
14561 DestroyWindow(window);
14564 static BOOL CALLBACK test_window_position_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect,
14565 LPARAM lparam)
14567 RECT primary_rect, window_rect, new_rect;
14568 IDirectDraw *ddraw;
14569 HWND window;
14570 HRESULT hr;
14571 BOOL ret;
14573 ddraw = create_ddraw();
14574 ok(!!ddraw, "Failed to create a ddraw object.\n");
14575 window = CreateWindowA("static", "ddraw_test", WS_POPUP | WS_VISIBLE, monitor_rect->left,
14576 monitor_rect->top, 100, 100, NULL, NULL, NULL, NULL);
14577 ok(!!window, "Failed to create a window.\n");
14578 flush_events();
14580 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
14581 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
14582 flush_events();
14583 ret = GetWindowRect(window, &window_rect);
14584 ok(ret, "GetWindowRect failed, error %lu.\n", GetLastError());
14585 SetRect(&primary_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
14586 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
14587 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
14589 new_rect = window_rect;
14590 --new_rect.right;
14591 --new_rect.bottom;
14593 ret = MoveWindow(window, new_rect.left, new_rect.top, new_rect.right - new_rect.left,
14594 new_rect.bottom - new_rect.top, TRUE);
14595 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
14596 ret = GetWindowRect(window, &window_rect);
14597 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
14598 ok(EqualRect(&window_rect, &new_rect),
14599 "Expected window rect %s, got %s.\n",
14600 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
14601 /* After processing window events window rectangle gets restored. But only once, the size set
14602 * on the second resize remains. */
14603 flush_events();
14604 ret = GetWindowRect(window, &window_rect);
14605 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
14606 /* Both Windows and Wine change the size of the window. On Windows it is exactly the new size but in Wine
14607 * it may get adjusted depending on window manager. */
14608 ok(window_rect.right != monitor_rect->right && window_rect.bottom != monitor_rect->bottom,
14609 "Expected window rect %s, got %s.\n",
14610 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
14612 ret = MoveWindow(window, new_rect.left, new_rect.top, new_rect.right - new_rect.left,
14613 new_rect.bottom - new_rect.top, TRUE);
14614 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
14615 ret = GetWindowRect(window, &window_rect);
14616 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
14617 ok(EqualRect(&window_rect, &new_rect),
14618 "Expected window rect %s, got %s.\n",
14619 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
14620 flush_events();
14621 ret = GetWindowRect(window, &window_rect);
14622 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
14623 ok(window_rect.right != monitor_rect->right && window_rect.bottom != monitor_rect->bottom,
14624 "Expected window rect %s, got %s.\n",
14625 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
14627 /* Window activation should restore the window to fit the whole primary monitor */
14628 ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0,
14629 SWP_NOZORDER | SWP_NOSIZE);
14630 ok(ret, "SetWindowPos failed, error %lu.\n", GetLastError());
14631 ret = SetForegroundWindow(GetDesktopWindow());
14632 ok(ret, "Failed to set foreground window.\n");
14633 flush_events();
14634 ret = ShowWindow(window, SW_RESTORE);
14635 ok(ret, "Failed to restore window, error %lu.\n", GetLastError());
14636 flush_events();
14637 ret = SetForegroundWindow(window);
14638 ok(ret, "SetForegroundWindow failed, error %lu.\n", GetLastError());
14639 flush_events();
14640 ret = GetWindowRect(window, &window_rect);
14641 ok(ret, "GetWindowRect failed, error %lu.\n", GetLastError());
14642 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
14643 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
14645 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
14646 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
14647 ret = GetWindowRect(window, &window_rect);
14648 ok(ret, "GetWindowRect failed, error %lu.\n", GetLastError());
14649 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
14650 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
14652 DestroyWindow(window);
14653 IDirectDraw_Release(ddraw);
14654 return TRUE;
14657 static void test_window_position(void)
14659 EnumDisplayMonitors(NULL, NULL, test_window_position_cb, 0);
14662 static BOOL CALLBACK test_get_display_mode_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect,
14663 LPARAM lparam)
14665 DDSURFACEDESC surface_desc;
14666 IDirectDraw *ddraw;
14667 HWND window;
14668 HRESULT hr;
14669 BOOL ret;
14671 ddraw = create_ddraw();
14672 ok(!!ddraw, "Failed to create a ddraw object.\n");
14673 window = create_window();
14674 ok(!!window, "Failed to create a window.\n");
14676 /* Test that DirectDraw doesn't use the device window to determine which monitor to use */
14677 ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0,
14678 SWP_NOZORDER | SWP_NOSIZE);
14679 ok(ret, "SetWindowPos failed, error %lu.\n", GetLastError());
14681 surface_desc.dwSize = sizeof(surface_desc);
14682 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
14683 ok(hr == DD_OK, "GetDisplayMode failed, hr %#lx.\n", hr);
14684 ok(surface_desc.dwWidth == GetSystemMetrics(SM_CXSCREEN), "Expect width %d, got %lu.\n",
14685 GetSystemMetrics(SM_CXSCREEN), surface_desc.dwWidth);
14686 ok(surface_desc.dwHeight == GetSystemMetrics(SM_CYSCREEN), "Expect height %d, got %lu.\n",
14687 GetSystemMetrics(SM_CYSCREEN), surface_desc.dwHeight);
14689 DestroyWindow(window);
14690 IDirectDraw_Release(ddraw);
14691 return TRUE;
14694 static void test_get_display_mode(void)
14696 static const DWORD flags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_REFRESHRATE | DDSD_PIXELFORMAT | DDSD_PITCH;
14697 DDSURFACEDESC surface_desc;
14698 IDirectDraw *ddraw;
14699 DEVMODEW devmode;
14700 HRESULT hr;
14701 BOOL ret;
14703 EnumDisplayMonitors(NULL, NULL, test_get_display_mode_cb, 0);
14705 ddraw = create_ddraw();
14706 ok(!!ddraw, "Failed to create a ddraw object.\n");
14708 memset(&devmode, 0, sizeof(devmode));
14709 devmode.dmSize = sizeof(devmode);
14710 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
14711 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
14713 surface_desc.dwSize = sizeof(surface_desc);
14714 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
14715 ok(hr == DD_OK, "GetDisplayMode failed, hr %#lx.\n", hr);
14716 ok(surface_desc.dwSize == sizeof(surface_desc), "Got dwSize %lu.\n", surface_desc.dwSize);
14717 ok(surface_desc.dwFlags == flags, "Expected dwFlags %#lx, got %#lx.\n", flags,
14718 surface_desc.dwFlags);
14719 ok(surface_desc.dwWidth == devmode.dmPelsWidth, "Expected width %lu, got %lu.\n",
14720 devmode.dmPelsWidth, surface_desc.dwWidth);
14721 ok(surface_desc.dwHeight == devmode.dmPelsHeight, "Expected height %lu, got %lu.\n",
14722 devmode.dmPelsHeight, surface_desc.dwHeight);
14723 ok(surface_desc.dwRefreshRate == devmode.dmDisplayFrequency, "Expected frequency %lu, got %lu.\n",
14724 devmode.dmDisplayFrequency, surface_desc.dwRefreshRate);
14725 ok(surface_desc.ddpfPixelFormat.dwSize == sizeof(surface_desc.ddpfPixelFormat),
14726 "Got ddpfPixelFormat.dwSize %lu.\n", surface_desc.ddpfPixelFormat.dwSize);
14727 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == devmode.dmBitsPerPel,
14728 "Expected ddpfPixelFormat.dwRGBBitCount %lu, got %lu.\n", devmode.dmBitsPerPel,
14729 surface_desc.ddpfPixelFormat.dwRGBBitCount);
14730 ok(surface_desc.lPitch == devmode.dmPelsWidth * devmode.dmBitsPerPel / 8,
14731 "Expected pitch %lu, got %lu.\n", devmode.dmPelsWidth * devmode.dmBitsPerPel / 8,
14732 surface_desc.lPitch);
14734 IDirectDraw_Release(ddraw);
14737 static void run_for_each_device_type(void (*test_func)(const GUID *))
14739 test_func(&IID_IDirect3DHALDevice);
14740 test_func(&IID_IDirect3DRGBDevice);
14743 static void test_texture_wrong_caps(const GUID *device_guid)
14745 static D3DTLVERTEX quad[] =
14747 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
14748 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
14749 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
14750 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
14752 static DDPIXELFORMAT fmt =
14754 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
14755 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
14757 unsigned int inst_length, color, expected_color;
14758 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
14759 IDirect3DExecuteBuffer *execute_buffer;
14760 IDirectDrawSurface *surface, *rt;
14761 D3DTEXTUREHANDLE texture_handle;
14762 D3DEXECUTEBUFFERDESC exec_desc;
14763 IDirect3DMaterial *background;
14764 IDirect3DViewport *viewport;
14765 IDirect3DTexture *texture;
14766 IDirect3DDevice *device;
14767 IDirectDraw *ddraw;
14768 DDSURFACEDESC ddsd;
14769 ULONG refcount;
14770 HWND window;
14771 HRESULT hr;
14772 void *ptr;
14774 window = create_window();
14775 ddraw = create_ddraw();
14776 ok(!!ddraw, "Failed to create a ddraw object.\n");
14777 if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid)))
14779 skip("Failed to create a 3D device, skipping test.\n");
14780 DestroyWindow(window);
14781 return;
14783 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
14784 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14786 viewport = create_viewport(device, 0, 0, 640, 480);
14788 memset(&ddsd, 0, sizeof(ddsd));
14789 ddsd.dwSize = sizeof(ddsd);
14790 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
14791 ddsd.dwHeight = 16;
14792 ddsd.dwWidth = 16;
14793 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
14794 ddsd.ddpfPixelFormat = fmt;
14795 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
14796 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14797 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
14798 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14799 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
14800 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14802 fill_surface(surface, 0xff00ff00);
14804 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
14805 viewport_set_background(device, viewport, background);
14807 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
14808 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14809 if (is_software_device_type(device_guid))
14810 fill_surface(rt, 0xffff0000);
14812 memset(&exec_desc, 0, sizeof(exec_desc));
14813 exec_desc.dwSize = sizeof(exec_desc);
14814 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
14815 exec_desc.dwBufferSize = 1024;
14816 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
14817 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
14818 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14820 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
14821 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14822 memcpy(exec_desc.lpData, quad, sizeof(quad));
14823 ptr = (BYTE *)exec_desc.lpData + sizeof(quad);
14824 emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 4);
14825 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
14826 emit_set_rs(&ptr, D3DRENDERSTATE_LIGHTING, FALSE);
14827 emit_tquad(&ptr, 0);
14828 emit_end(&ptr);
14829 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData - sizeof(quad);
14830 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
14831 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14833 set_execute_data(execute_buffer, 4, sizeof(quad), inst_length);
14835 hr = IDirect3DDevice_BeginScene(device);
14836 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14837 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
14838 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14839 hr = IDirect3DDevice_EndScene(device);
14840 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14842 expected_color = is_software_device_type(device_guid) ? 0x0000ff00 : 0x00ffffff;
14843 color = get_surface_color(rt, 320, 240);
14844 ok(compare_color(color, expected_color, 1), "Got color 0x%08x, expected 0x%08x.\n", color, expected_color);
14846 IDirect3DTexture_Release(texture);
14847 IDirectDrawSurface_Release(surface);
14848 IDirectDrawSurface_Release(rt);
14849 IDirect3DExecuteBuffer_Release(execute_buffer);
14850 destroy_material(background);
14851 destroy_viewport(device, viewport);
14853 IDirect3DDevice_Release(device);
14854 refcount = IDirectDraw_Release(ddraw);
14855 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
14856 DestroyWindow(window);
14859 static void test_filling_convention(void)
14861 unsigned int inst_length, colour, expected, i, x, y;
14862 static const DWORD colour_bottom = 0x00ffff00;
14863 static const DWORD colour_clear = 0x000000ff;
14864 static const DWORD colour_right = 0x00000000;
14865 static const DWORD colour_left = 0x00ff0000;
14866 static const DWORD colour_top = 0x0000ff00;
14867 IDirect3DExecuteBuffer *execute_buffer;
14868 D3DEXECUTEBUFFERDESC exec_desc;
14869 IDirectDrawSurface *backbuffer;
14870 IDirect3DMaterial *background;
14871 IDirect3DViewport *viewport;
14872 IDirect3DDevice *device;
14873 IDirectDraw *ddraw;
14874 ULONG refcount;
14875 HWND window;
14876 HRESULT hr;
14877 BOOL todo;
14878 void *ptr;
14880 static const unsigned int vp_size = 8;
14881 D3DRECT clear_rect = {{0}, {0}, {vp_size}, {vp_size}};
14883 /* This test data follows the examples in MSDN's
14884 * "Rasterization Rules (Direct3D 9)" article.
14886 * See the d3d9 test for a comment about the eps value. */
14887 static const float eps = 1.0f / 64.0f;
14888 D3DLVERTEX center_tris[] =
14890 /* left */
14891 {{-2.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_left}},
14892 {{-2.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_left}},
14893 {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_left}},
14895 /* top */
14896 {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_top}},
14897 {{-2.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_top}},
14898 {{-0.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_top}},
14900 /* right */
14901 {{-0.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_right}},
14902 {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_right}},
14903 {{-0.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_right}},
14905 /* bottom */
14906 {{-2.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_bottom}},
14907 {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_bottom}},
14908 {{-0.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_bottom}},
14910 edge_tris[] =
14912 /* left */
14913 {{-2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
14914 {{-2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
14915 {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
14917 /* top */
14918 {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
14919 {{-2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
14920 {{ 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
14922 /* right */
14923 {{ 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
14924 {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
14925 {{ 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
14927 /* bottom */
14928 {{-2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
14929 {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
14930 {{ 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
14932 nudge_right_tris[] =
14934 /* left */
14935 {{eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
14936 {{eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
14937 {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
14939 /* top */
14940 {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
14941 {{eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
14942 {{eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
14944 /* right */
14945 {{eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
14946 {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
14947 {{eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
14949 /* bottom */
14950 {{eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
14951 {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
14952 {{eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
14954 nudge_left_tris[] =
14956 {{-eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
14957 {{-eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
14958 {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
14960 /* top */
14961 {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
14962 {{-eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
14963 {{-eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
14965 /* right */
14966 {{-eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
14967 {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
14968 {{-eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
14970 /* bottom */
14971 {{-eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
14972 {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
14973 {{-eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
14975 nudge_top_tris[] =
14977 /* left */
14978 {{-2.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
14979 {{-2.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
14980 {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
14982 /* top */
14983 {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
14984 {{-2.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
14985 {{ 0.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
14987 /* right */
14988 {{ 0.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
14989 {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
14990 {{ 0.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
14992 /* bottom */
14993 {{-2.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
14994 {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
14995 {{ 0.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
14997 nudge_bottom_tris[] =
14999 /* left */
15000 {{-2.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15001 {{-2.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15002 {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15004 /* top */
15005 {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15006 {{-2.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15007 {{ 0.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15009 /* right */
15010 {{ 0.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15011 {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15012 {{ 0.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15014 /* bottom */
15015 {{-2.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15016 {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15017 {{ 0.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15020 D3DTLVERTEX center_tris_t[] =
15022 /* left */
15023 {{1.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_left}},
15024 {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_left}},
15025 {{1.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_left}},
15027 /* top */
15028 {{1.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_top}},
15029 {{3.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_top}},
15030 {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_top}},
15032 /* right */
15033 {{3.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_right}},
15034 {{3.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_right}},
15035 {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_right}},
15037 /* bottom */
15038 {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_bottom}},
15039 {{3.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_bottom}},
15040 {{1.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_bottom}},
15042 edge_tris_t[] =
15044 /* left */
15045 {{2.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_left}},
15046 {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_left}},
15047 {{2.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_left}},
15049 /* top */
15050 {{2.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_top}},
15051 {{4.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_top}},
15052 {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_top}},
15054 /* right */
15055 {{4.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_right}},
15056 {{4.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_right}},
15057 {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_right}},
15059 /* bottom */
15060 {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_bottom}},
15061 {{4.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_bottom}},
15062 {{2.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_bottom}},
15065 const struct
15067 void *geometry;
15068 DWORD op;
15069 const char *expected[8];
15071 tests[] =
15074 center_tris,
15075 D3DPROCESSVERTICES_TRANSFORM,
15077 " ",
15078 " ",
15079 " TT ",
15080 " LR ",
15081 " LR ",
15082 " BB ",
15083 " ",
15088 edge_tris,
15089 D3DPROCESSVERTICES_TRANSFORM,
15091 " ",
15092 " TT ",
15093 " LT ",
15094 " LR ",
15095 " LB ",
15096 " ",
15097 " ",
15102 nudge_right_tris,
15103 D3DPROCESSVERTICES_TRANSFORM,
15105 " ",
15106 " TT ",
15107 " TR ",
15108 " LR ",
15109 " BR ",
15110 " ",
15111 " ",
15116 nudge_left_tris,
15117 D3DPROCESSVERTICES_TRANSFORM,
15119 " ",
15120 " TT ",
15121 " LT ",
15122 " LR ",
15123 " LB ",
15124 " ",
15125 " ",
15130 nudge_top_tris,
15131 D3DPROCESSVERTICES_TRANSFORM,
15133 " ",
15134 " LT ",
15135 " LT ",
15136 " LB ",
15137 " LB ",
15138 " ",
15139 " ",
15144 nudge_bottom_tris,
15145 D3DPROCESSVERTICES_TRANSFORM,
15147 " ",
15148 " ",
15149 " LT ",
15150 " Lt ",
15151 " LB ",
15152 " lB ",
15153 " ",
15158 center_tris_t,
15159 D3DPROCESSVERTICES_COPY,
15161 " ",
15162 " ",
15163 " TT ",
15164 " LR ",
15165 " LR ",
15166 " BB ",
15167 " ",
15172 edge_tris_t,
15173 D3DPROCESSVERTICES_COPY,
15175 " ",
15176 " TT ",
15177 " LT ",
15178 " LR ",
15179 " LB ",
15180 " ",
15181 " ",
15186 static WORD indices[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
15188 window = create_window();
15189 ddraw = create_ddraw();
15190 ok(!!ddraw, "Failed to create a ddraw object.\n");
15191 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
15193 skip("Failed to create a 3D device.\n");
15194 IDirectDraw_Release(ddraw);
15195 DestroyWindow(window);
15196 return;
15199 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&backbuffer);
15200 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15202 viewport = create_viewport(device, 0, 0, vp_size, vp_size);
15203 background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
15204 viewport_set_background(device, viewport, background);
15206 memset(&exec_desc, 0, sizeof(exec_desc));
15207 exec_desc.dwSize = sizeof(exec_desc);
15208 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
15209 exec_desc.dwBufferSize = 1024;
15210 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
15212 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
15213 ok(hr == D3D_OK, "Failed to create execute buffer, hr %#lx.\n", hr);
15215 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15217 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
15218 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15220 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
15221 ok(hr == D3D_OK, "Failed to lock execute buffer, hr %#lx.\n", hr);
15223 /* All test geometry has the same vertex count and vertex size. */
15224 memcpy(exec_desc.lpData, tests[i].geometry, sizeof(center_tris));
15225 ptr = ((BYTE *)exec_desc.lpData) + sizeof(center_tris);
15226 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, FALSE);
15227 /* Old WARP versions (w8, early win10) apply color keying without textures. */
15228 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, FALSE);
15230 emit_process_vertices(&ptr, tests[i].op, 0, 12);
15231 emit_tri_indices(&ptr, indices, 4);
15232 emit_end(&ptr);
15233 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
15234 inst_length -= sizeof(center_tris);
15236 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
15237 ok(hr == D3D_OK, "Failed to lock execute buffer, hr %#lx.\n", hr);
15239 set_execute_data(execute_buffer, 12, sizeof(center_tris), inst_length);
15241 hr = IDirect3DDevice_BeginScene(device);
15242 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15243 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
15244 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15245 hr = IDirect3DDevice_EndScene(device);
15246 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15248 for (y = 0; y < 8; y++)
15250 for (x = 0; x < 8; x++)
15252 todo = FALSE;
15253 switch (tests[i].expected[y][x])
15255 case 'l': todo = TRUE;
15256 case 'L':
15257 expected = colour_left;
15258 break;
15259 case 't': todo = TRUE;
15260 case 'T':
15261 expected = colour_top;
15262 break;
15263 case 'r': todo = TRUE;
15264 case 'R':
15265 expected = colour_right;
15266 break;
15267 case 'b': todo = TRUE;
15268 case 'B':
15269 expected = colour_bottom;
15270 break;
15271 case ' ':
15272 expected = colour_clear;
15273 break;
15274 default:
15275 ok(0, "Unexpected entry in expected test char\n");
15276 expected = 0xdeadbeef;
15278 colour = get_surface_color(backbuffer, x, y);
15279 /* The nudge-to-bottom test fails on cards that give us a bottom-left
15280 * filling convention. The cause isn't the bottom part of the filling
15281 * convention, but because wined3d will nudge geometry to the left to
15282 * keep diagonals (the 'R' in test case 'edge_tris') intact. */
15283 todo_wine_if(todo && !compare_color(colour, expected, 1))
15284 ok(compare_color(colour, expected, 1), "Got unexpected colour %08x, %ux%u, case %u.\n",
15285 colour, x, y, i);
15290 destroy_viewport(device, viewport);
15291 IDirectDrawSurface_Release(backbuffer);
15292 IDirect3DDevice_Release(device);
15293 refcount = IDirectDraw_Release(ddraw);
15294 ok(!refcount, "Device has %lu references left.\n", refcount);
15295 DestroyWindow(window);
15298 static HRESULT WINAPI test_enum_devices_caps_callback(GUID *guid, char *device_desc,
15299 char *device_name, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, void *ctx)
15301 if(IsEqualGUID(&IID_IDirect3DRGBDevice, guid))
15303 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
15304 "RGB Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n");
15305 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
15306 "RGB Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n");
15307 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
15308 "RGB Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
15309 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
15310 "RGB Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
15312 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
15313 "RGB Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
15314 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
15315 "RGB Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
15316 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
15317 "RGB Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
15318 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
15319 "RGB Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
15321 ok(hal->dcmColorModel == 0, "RGB Device hal caps has colormodel %lu\n", hal->dcmColorModel);
15322 ok(hel->dcmColorModel == D3DCOLOR_RGB, "RGB Device hel caps has colormodel %lu\n", hel->dcmColorModel);
15324 ok(hal->dwFlags == 0, "RGB Device hal caps has hardware flags %#lx\n", hal->dwFlags);
15325 ok(hel->dwFlags != 0, "RGB Device hel caps has hardware flags %#lx\n", hel->dwFlags);
15327 ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
15328 "RGB Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
15329 ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
15330 "RGB Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
15331 ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
15332 "RGB Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
15333 ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
15334 "RGB Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
15335 ok((hal->dwDevCaps & D3DDEVCAPS_HWRASTERIZATION) == 0,
15336 "RGB Device hal device caps has D3DDEVCAPS_HWRASTERIZATION set\n");
15337 ok((hel->dwDevCaps & D3DDEVCAPS_HWRASTERIZATION) == 0,
15338 "RGB Device hel device caps has D3DDEVCAPS_HWRASTERIZATION set\n");
15340 else if(IsEqualGUID(&IID_IDirect3DHALDevice, guid))
15342 ok(hal->dcmColorModel == D3DCOLOR_RGB, "HAL Device hal caps has colormodel %lu\n", hel->dcmColorModel);
15343 ok(hel->dcmColorModel == 0, "HAL Device hel caps has colormodel %lu\n", hel->dcmColorModel);
15345 ok(hal->dwFlags != 0, "HAL Device hal caps has hardware flags %#lx\n", hal->dwFlags);
15346 ok(hel->dwFlags != 0, "HAL Device hel caps has hardware flags %#lx\n", hel->dwFlags);
15348 ok(hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT,
15349 "HAL Device hal device caps does not have D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
15350 ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
15351 "RGB Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
15352 ok(hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX,
15353 "HAL Device hal device caps does not have D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
15354 ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
15355 "RGB Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
15357 else if(IsEqualGUID(&IID_IDirect3DRefDevice, guid))
15359 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
15360 "REF Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n");
15361 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
15362 "REF Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n");
15363 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
15364 "REF Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
15365 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
15366 "REF Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
15368 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
15369 "REF Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
15370 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
15371 "REF Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
15372 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
15373 "REF Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
15374 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
15375 "REF Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
15377 ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
15378 "REF Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
15379 ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
15380 "REF Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
15381 ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
15382 "REF Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
15383 ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
15384 "REF Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
15386 else if(IsEqualGUID(&IID_IDirect3DRampDevice, guid))
15388 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
15389 "Ramp Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n");
15390 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
15391 "Ramp Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n");
15392 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
15393 "Ramp Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
15394 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
15395 "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
15397 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
15398 "Ramp Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
15399 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
15400 "Ramp Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
15401 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
15402 "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
15403 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
15404 "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
15406 ok(hal->dcmColorModel == 0, "Ramp Device hal caps has colormodel %lu\n", hal->dcmColorModel);
15407 ok(hel->dcmColorModel == D3DCOLOR_MONO, "Ramp Device hel caps has colormodel %lu\n",
15408 hel->dcmColorModel);
15410 ok(hal->dwFlags == 0, "Ramp Device hal caps has hardware flags %#lx\n", hal->dwFlags);
15411 ok(hel->dwFlags != 0, "Ramp Device hel caps has hardware flags %#lx\n", hel->dwFlags);
15413 ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
15414 "Ramp Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
15415 ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
15416 "Ramp Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
15417 ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
15418 "Ramp Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
15419 ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
15420 "Ramp Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
15422 else if(IsEqualGUID(&IID_IDirect3DMMXDevice, guid))
15424 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
15425 "MMX Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n");
15426 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
15427 "MMX Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n");
15428 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
15429 "MMX Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
15430 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
15431 "MMX Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
15433 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
15434 "MMX Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
15435 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
15436 "MMX Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
15437 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
15438 "MMX Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
15439 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
15440 "MMX Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
15442 ok(hal->dcmColorModel == 0, "MMX Device hal caps has colormodel %lu\n", hal->dcmColorModel);
15443 ok(hel->dcmColorModel == D3DCOLOR_RGB, "MMX Device hel caps has colormodel %lu\n", hel->dcmColorModel);
15445 ok(hal->dwFlags == 0, "MMX Device hal caps has hardware flags %#lx\n", hal->dwFlags);
15446 ok(hel->dwFlags != 0, "MMX Device hel caps has hardware flags %#lx\n", hel->dwFlags);
15448 ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
15449 "MMX Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
15450 ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
15451 "MMX Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
15452 ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
15453 "MMX Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
15454 ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
15455 "MMX Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
15457 else
15459 ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", device_desc, device_name);
15460 if (hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)
15461 trace("hal line has pow2 set\n");
15462 else
15463 trace("hal line does NOT have pow2 set\n");
15464 if (hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)
15465 trace("hal tri has pow2 set\n");
15466 else
15467 trace("hal tri does NOT have pow2 set\n");
15468 if (hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)
15469 trace("hel line has pow2 set\n");
15470 else
15471 trace("hel line does NOT have pow2 set\n");
15472 if (hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)
15473 trace("hel tri has pow2 set\n");
15474 else
15475 trace("hel tri does NOT have pow2 set\n");
15478 return DDENUMRET_OK;
15481 static void test_enum_devices(void)
15483 IDirectDraw *ddraw;
15484 IDirect3D *d3d;
15485 ULONG refcount;
15486 HRESULT hr;
15488 ddraw = create_ddraw();
15489 ok(!!ddraw, "Failed to create a ddraw object.\n");
15491 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
15492 if (FAILED(hr))
15494 skip("D3D interface is not available, skipping test.\n");
15495 IDirectDraw_Release(ddraw);
15496 return;
15499 hr = IDirect3D_EnumDevices(d3d, NULL, NULL);
15500 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
15502 hr = IDirect3D_EnumDevices(d3d, test_enum_devices_caps_callback, NULL);
15503 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
15505 IDirect3D_Release(d3d);
15506 refcount = IDirectDraw_Release(ddraw);
15507 ok(!refcount, "Device has %lu references left.\n", refcount);
15510 /* Emperor: Rise of the Middle Kingdom locks a sysmem surface and then accesses
15511 * the pointer after unlocking it. This test roughly replicates the calls that
15512 * it makes. */
15513 static void test_pinned_sysmem(void)
15515 DDBLTFX fx = {.dwSize = sizeof(fx), .dwFillColor = 0xface};
15516 IDirectDrawSurface *surface, *surface2;
15517 DDSURFACEDESC surface_desc;
15518 unsigned int color;
15519 IDirectDraw *ddraw;
15520 ULONG refcount;
15521 HWND window;
15522 HRESULT hr;
15524 window = create_window();
15525 ddraw = create_ddraw();
15526 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
15527 ok(hr == S_OK, "Got hr %#lx.\n", hr);
15529 memset(&surface_desc, 0, sizeof(surface_desc));
15530 surface_desc.dwSize = sizeof(surface_desc);
15531 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
15532 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
15533 surface_desc.dwWidth = 32;
15534 surface_desc.dwHeight = 32;
15535 init_format_b5g6r5(&surface_desc.ddpfPixelFormat);
15536 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
15537 ok(hr == S_OK, "Got hr %#lx.\n", hr);
15538 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
15539 ok(hr == S_OK, "Got hr %#lx.\n", hr);
15541 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15542 ok(hr == S_OK, "Got hr %#lx.\n", hr);
15543 hr = IDirectDrawSurface_Unlock(surface, NULL);
15544 ok(hr == S_OK, "Got hr %#lx.\n", hr);
15546 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
15547 ok(hr == S_OK, "Got hr %#lx.\n", hr);
15549 color = ((unsigned short *)surface_desc.lpSurface)[0];
15550 ok(color == 0xface, "Got color %04x.\n", color);
15552 memset(surface_desc.lpSurface, 0x55, 32 * 16 * 2);
15554 hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface, NULL, DDBLTFAST_WAIT);
15555 ok(hr == S_OK, "Got hr %#lx.\n", hr);
15557 hr = IDirectDrawSurface_Lock(surface2, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15558 ok(hr == S_OK, "Got hr %#lx.\n", hr);
15559 color = ((unsigned short *)surface_desc.lpSurface)[0];
15560 ok(color == 0x5555, "Got color %04x.\n", color);
15561 color = ((unsigned short *)surface_desc.lpSurface)[32 * 16];
15562 ok(color == 0xface, "Got color %04x.\n", color);
15563 hr = IDirectDrawSurface_Unlock(surface2, NULL);
15564 ok(hr == S_OK, "Got hr %#lx.\n", hr);
15566 IDirectDrawSurface_Release(surface2);
15567 IDirectDrawSurface_Release(surface);
15568 refcount = IDirectDraw_Release(ddraw);
15569 ok(!refcount, "Device has %lu references left.\n", refcount);
15570 DestroyWindow(window);
15573 static void test_multiple_devices(void)
15575 static D3DMATRIX test_matrix =
15577 1.0f, 0.0f, 0.0f, 0.0f,
15578 0.0f, 2.0f, 0.0f, 0.0f,
15579 0.0f, 0.0f, 3.0f, 0.0f,
15580 0.0f, 0.0f, 0.0f, 4.0f,
15583 D3DTEXTUREHANDLE texture_handle, texture_handle2;
15584 D3DMATERIALHANDLE mat_handle, mat_handle2;
15585 IDirect3DViewport *viewport, *viewport2;
15586 IDirect3DDevice *device, *device2;
15587 IDirectDrawSurface *texture_surf;
15588 D3DMATRIXHANDLE matrix_handle;
15589 IDirectDraw *ddraw, *ddraw2;
15590 IDirect3DMaterial *material;
15591 DDSURFACEDESC surface_desc;
15592 IDirect3DTexture *texture;
15593 D3DMATRIX matrix;
15594 ULONG refcount;
15595 HWND window;
15596 HRESULT hr;
15598 window = create_window();
15599 ddraw = create_ddraw();
15600 ok(!!ddraw, "Failed to create a ddraw object.\n");
15602 if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, &IID_IDirect3DHALDevice)))
15604 skip("Failed to create a 3D device, skipping test.\n");
15605 DestroyWindow(window);
15606 return;
15609 ddraw2 = create_ddraw();
15610 ok(!!ddraw2, "Failed to create a ddraw object.\n");
15612 device2 = create_device_ex(ddraw2, window, DDSCL_NORMAL, &IID_IDirect3DHALDevice);
15613 ok(!!device2, "got NULL.\n");
15615 viewport = create_viewport(device, 0, 0, 640, 480);
15616 viewport2 = create_viewport(device2, 0, 0, 640, 480);
15618 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
15619 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
15620 ok(hr == D3D_OK, "got %#lx.\n", hr);
15621 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle2);
15622 ok(hr == D3D_OK, "got %#lx.\n", hr);
15623 ok(mat_handle == mat_handle2, "got different handles.\n");
15625 hr = IDirect3DMaterial_GetHandle(material, device2, &mat_handle2);
15626 ok(hr == D3D_OK, "got %#lx.\n", hr);
15627 todo_wine ok(mat_handle != mat_handle2, "got same handles.\n");
15629 hr = IDirect3DViewport_SetBackground(viewport, mat_handle);
15630 ok(hr == D3D_OK, "got %#lx.\n", hr);
15631 hr = IDirect3DViewport_SetBackground(viewport2, mat_handle);
15632 ok(hr == D3D_OK, "got %#lx.\n", hr);
15634 memset(&surface_desc, 0, sizeof(surface_desc));
15635 surface_desc.dwSize = sizeof(surface_desc);
15636 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
15637 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
15638 surface_desc.dwWidth = 256;
15639 surface_desc.dwHeight = 256;
15640 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &texture_surf, NULL);
15641 ok(hr == D3D_OK, "got %#lx.\n", hr);
15642 hr = IDirectDrawSurface_QueryInterface(texture_surf, &IID_IDirect3DTexture2, (void **)&texture);
15643 ok(hr == D3D_OK, "got %#lx.\n", hr);
15644 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
15645 ok(hr == D3D_OK, "got %#lx.\n", hr);
15646 hr = IDirect3DTexture_GetHandle(texture, device2, &texture_handle2);
15647 ok(hr == D3D_OK, "got %#lx.\n", hr);
15648 ok(texture_handle != texture_handle2, "got same handles.\n");
15650 hr = IDirect3DDevice_CreateMatrix(device, &matrix_handle);
15651 ok(hr == D3D_OK, "got %#lx.\n", hr);
15652 hr = IDirect3DDevice_SetMatrix(device, matrix_handle, &test_matrix);
15653 ok(hr == D3D_OK, "got %#lx.\n", hr);
15655 memset(&matrix, 0xcc, sizeof(matrix));
15656 hr = IDirect3DDevice_GetMatrix(device2, matrix_handle, &matrix);
15657 ok(hr == D3D_OK, "got %#lx.\n", hr);
15658 ok(!memcmp(&matrix, &test_matrix, sizeof(matrix)), "matrix does not match.\n");
15660 IDirect3DTexture_Release(texture);
15661 IDirectDrawSurface_Release(texture_surf);
15662 IDirect3DMaterial_Release(material);
15663 IDirect3DViewport_Release(viewport);
15664 IDirect3DViewport_Release(viewport2);
15666 refcount = IDirect3DDevice_Release(device);
15667 ok(!refcount, "Device has %lu references left.\n", refcount);
15668 refcount = IDirect3DDevice_Release(device2);
15669 ok(!refcount, "Device has %lu references left.\n", refcount);
15671 IDirectDraw_Release(ddraw);
15672 IDirectDraw_Release(ddraw2);
15673 DestroyWindow(window);
15676 START_TEST(ddraw1)
15678 DDDEVICEIDENTIFIER identifier;
15679 DEVMODEW current_mode;
15680 IDirectDraw *ddraw;
15681 HMODULE dwmapi;
15683 if (!(ddraw = create_ddraw()))
15685 skip("Failed to create a ddraw object, skipping tests.\n");
15686 return;
15689 if (ddraw_get_identifier(ddraw, &identifier))
15691 trace("Driver string: \"%s\"\n", identifier.szDriver);
15692 trace("Description string: \"%s\"\n", identifier.szDescription);
15693 trace("Driver version %d.%d.%d.%d\n",
15694 HIWORD(identifier.liDriverVersion.HighPart), LOWORD(identifier.liDriverVersion.HighPart),
15695 HIWORD(identifier.liDriverVersion.LowPart), LOWORD(identifier.liDriverVersion.LowPart));
15697 IDirectDraw_Release(ddraw);
15699 memset(&current_mode, 0, sizeof(current_mode));
15700 current_mode.dmSize = sizeof(current_mode);
15701 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
15702 registry_mode.dmSize = sizeof(registry_mode);
15703 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
15704 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
15705 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
15707 skip("Current mode does not match registry mode, skipping test.\n");
15708 return;
15711 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
15712 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
15714 test_coop_level_create_device_window();
15715 test_clipper_blt();
15716 test_coop_level_d3d_state();
15717 test_surface_interface_mismatch();
15718 test_coop_level_threaded();
15719 test_viewport_object();
15720 run_for_each_device_type(test_zenable);
15721 run_for_each_device_type(test_ck_rgba);
15722 test_ck_default();
15723 test_ck_complex();
15724 test_surface_qi();
15725 test_device_qi();
15726 test_wndproc();
15727 test_window_style();
15728 test_redundant_mode_set();
15729 test_coop_level_mode_set();
15730 test_coop_level_mode_set_multi();
15731 test_initialize();
15732 test_coop_level_surf_create();
15733 test_coop_level_multi_window();
15734 test_clear_rect_count();
15735 test_coop_level_activateapp();
15736 test_unsupported_formats();
15737 run_for_each_device_type(test_rt_caps);
15738 test_primary_caps();
15739 test_surface_lock();
15740 test_surface_discard();
15741 test_flip();
15742 test_sysmem_overlay();
15743 test_primary_palette();
15744 test_surface_attachment();
15745 test_pixel_format();
15746 test_create_surface_pitch();
15747 test_mipmap();
15748 test_palette_complex();
15749 test_p8_blit();
15750 test_material();
15751 test_lighting();
15752 test_specular_lighting();
15753 test_palette_gdi();
15754 test_palette_alpha();
15755 test_lost_device();
15756 test_surface_desc_lock();
15757 test_texturemapblend();
15758 test_viewport_clear_rect();
15759 test_color_fill();
15760 test_colorkey_precision();
15761 test_range_colorkey();
15762 test_shademode();
15763 test_lockrect_invalid();
15764 test_yv12_overlay();
15765 test_offscreen_overlay();
15766 test_overlay_rect();
15767 test_blt();
15768 test_blt_z_alpha();
15769 test_cross_device_blt();
15770 test_getdc();
15771 test_transform_vertices();
15772 test_display_mode_surface_pixel_format();
15773 test_surface_desc_size();
15774 test_texture_load();
15775 test_ck_operation();
15776 test_depth_readback();
15777 test_clear();
15778 test_enum_surfaces();
15779 test_execute_data();
15780 test_viewport();
15781 test_find_device();
15782 test_killfocus();
15783 test_gdi_surface();
15784 test_alphatest();
15785 test_clipper_refcount();
15786 test_caps();
15787 test_d32_support();
15788 test_cursor_clipping();
15789 test_vtbl_protection();
15790 test_window_position();
15791 test_get_display_mode();
15792 run_for_each_device_type(test_texture_wrong_caps);
15793 test_filling_convention();
15794 test_enum_devices();
15795 test_pinned_sysmem();
15796 test_multiple_devices();