include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / ddraw / tests / ddraw2.c
blob48a49815c585b49958ac8663c7033d1b950168cc
1 /*
2 * Copyright 2005 Antoine Chavasse (a.chavasse@gmail.com)
3 * Copyright 2008, 2011, 2012-2014 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 #include <math.h>
23 #define COBJMACROS
24 #include "wine/test.h"
25 #include <limits.h>
26 #include <math.h>
27 #include "ddrawi.h"
28 #include "d3dhal.h"
30 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
31 static DEVMODEW registry_mode;
33 static HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *);
35 struct vec2
37 float x, y;
40 struct vec4
42 float x, y, z, w;
45 struct create_window_thread_param
47 HWND window;
48 HANDLE window_created;
49 HANDLE destroy_window;
50 HANDLE thread;
53 static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff)
55 unsigned int diff = x > y ? x - y : y - x;
57 return diff <= max_diff;
60 static BOOL compare_float(float f, float g, unsigned int ulps)
62 int x = *(int *)&f;
63 int y = *(int *)&g;
65 if (x < 0)
66 x = INT_MIN - x;
67 if (y < 0)
68 y = INT_MIN - y;
70 return compare_uint(x, y, ulps);
73 static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
75 return compare_float(vec->x, x, ulps)
76 && compare_float(vec->y, y, ulps)
77 && compare_float(vec->z, z, ulps)
78 && compare_float(vec->w, w, ulps);
81 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
83 return compare_uint(c1 & 0xff, c2 & 0xff, max_diff)
84 && compare_uint((c1 >> 8) & 0xff, (c2 >> 8) & 0xff, max_diff)
85 && compare_uint((c1 >> 16) & 0xff, (c2 >> 16) & 0xff, max_diff)
86 && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff);
89 static void get_virtual_rect(RECT *rect)
91 rect->left = GetSystemMetrics(SM_XVIRTUALSCREEN);
92 rect->top = GetSystemMetrics(SM_YVIRTUALSCREEN);
93 rect->right = rect->left + GetSystemMetrics(SM_CXVIRTUALSCREEN);
94 rect->bottom = rect->top + GetSystemMetrics(SM_CYVIRTUALSCREEN);
97 /* Try to make sure pending X events have been processed before continuing */
98 static void flush_events(void)
100 int diff = 200;
101 DWORD time;
102 MSG msg;
104 time = GetTickCount() + diff;
105 while (diff > 0)
107 if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT)
108 break;
109 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
110 DispatchMessageA(&msg);
111 diff = time - GetTickCount();
115 static BOOL ddraw_get_identifier(IDirectDraw2 *ddraw, DDDEVICEIDENTIFIER *identifier)
117 IDirectDraw4 *ddraw4;
118 HRESULT hr;
120 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirectDraw4, (void **)&ddraw4);
121 ok(SUCCEEDED(hr), "Failed to get IDirectDraw4 interface, hr %#lx.\n", hr);
122 hr = IDirectDraw4_GetDeviceIdentifier(ddraw4, identifier, 0);
123 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#lx.\n", hr);
124 IDirectDraw4_Release(ddraw4);
126 return SUCCEEDED(hr);
129 static BOOL ddraw_is_warp(IDirectDraw2 *ddraw)
131 DDDEVICEIDENTIFIER identifier;
133 return strcmp(winetest_platform, "wine")
134 && ddraw_get_identifier(ddraw, &identifier)
135 && strstr(identifier.szDriver, "warp");
138 static BOOL ddraw_is_vendor(IDirectDraw2 *ddraw, DWORD vendor)
140 DDDEVICEIDENTIFIER identifier;
142 return strcmp(winetest_platform, "wine")
143 && ddraw_get_identifier(ddraw, &identifier)
144 && identifier.dwVendorId == vendor;
147 static BOOL ddraw_is_amd(IDirectDraw2 *ddraw)
149 return ddraw_is_vendor(ddraw, 0x1002);
152 static BOOL ddraw_is_intel(IDirectDraw2 *ddraw)
154 return ddraw_is_vendor(ddraw, 0x8086);
157 static BOOL ddraw_is_nvidia(IDirectDraw2 *ddraw)
159 return ddraw_is_vendor(ddraw, 0x10de);
162 static BOOL ddraw_is_vmware(IDirectDraw2 *ddraw)
164 return ddraw_is_vendor(ddraw, 0x15ad);
167 static BOOL is_software_device_type(const GUID *device_guid)
169 return device_guid != &IID_IDirect3DHALDevice;
172 static IDirectDrawSurface *create_overlay(IDirectDraw2 *ddraw,
173 unsigned int width, unsigned int height, DWORD format)
175 IDirectDrawSurface *surface;
176 DDSURFACEDESC desc;
178 memset(&desc, 0, sizeof(desc));
179 desc.dwSize = sizeof(desc);
180 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
181 desc.dwWidth = width;
182 desc.dwHeight = height;
183 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
184 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
185 desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
186 desc.ddpfPixelFormat.dwFourCC = format;
188 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &desc, &surface, NULL)))
189 return NULL;
190 return surface;
193 static HWND create_window(void)
195 RECT r = {0, 0, 640, 480};
197 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
199 return CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
200 CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
203 static DWORD WINAPI create_window_thread_proc(void *param)
205 struct create_window_thread_param *p = param;
206 DWORD res;
207 BOOL ret;
209 p->window = create_window();
210 ret = SetEvent(p->window_created);
211 ok(ret, "SetEvent failed, last error %lu.\n", GetLastError());
213 for (;;)
215 MSG msg;
217 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
218 DispatchMessageA(&msg);
219 res = WaitForSingleObject(p->destroy_window, 100);
220 if (res == WAIT_OBJECT_0)
221 break;
222 if (res != WAIT_TIMEOUT)
224 ok(0, "Wait failed (%#lx), last error %lu.\n", res, GetLastError());
225 break;
229 DestroyWindow(p->window);
231 return 0;
234 static void create_window_thread(struct create_window_thread_param *p)
236 DWORD res, tid;
238 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
239 ok(!!p->window_created, "CreateEvent failed, last error %lu.\n", GetLastError());
240 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
241 ok(!!p->destroy_window, "CreateEvent failed, last error %lu.\n", GetLastError());
242 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
243 ok(!!p->thread, "Failed to create thread, last error %lu.\n", GetLastError());
244 res = WaitForSingleObject(p->window_created, INFINITE);
245 ok(res == WAIT_OBJECT_0, "Wait failed (%#lx), last error %lu.\n", res, GetLastError());
248 static void destroy_window_thread(struct create_window_thread_param *p)
250 SetEvent(p->destroy_window);
251 WaitForSingleObject(p->thread, INFINITE);
252 CloseHandle(p->destroy_window);
253 CloseHandle(p->window_created);
254 CloseHandle(p->thread);
257 static IDirectDrawSurface *get_depth_stencil(IDirect3DDevice2 *device)
259 IDirectDrawSurface *rt, *ret;
260 DDSCAPS caps = {DDSCAPS_ZBUFFER};
261 HRESULT hr;
263 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
264 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
265 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ret);
266 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#lx.\n", hr);
267 IDirectDrawSurface_Release(rt);
268 return ret;
271 /* Free original_modes after finished using it */
272 static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
274 unsigned int number, size = 2, count = 0, index = 0;
275 DISPLAY_DEVICEW display_device;
276 DEVMODEW *modes, *tmp;
278 if (!(modes = malloc(size * sizeof(*modes))))
279 return FALSE;
281 display_device.cb = sizeof(display_device);
282 while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
284 /* Skip software devices */
285 if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
286 continue;
288 if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
289 continue;
291 if (count >= size)
293 size *= 2;
294 if (!(tmp = realloc(modes, size * sizeof(*modes))))
296 free(modes);
297 return FALSE;
299 modes = tmp;
302 memset(&modes[count], 0, sizeof(modes[count]));
303 modes[count].dmSize = sizeof(modes[count]);
304 if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
306 free(modes);
307 return FALSE;
310 lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
313 *original_modes = modes;
314 *display_count = count;
315 return TRUE;
318 static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
320 unsigned int index;
321 LONG ret;
323 for (index = 0; index < count; ++index)
325 ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
326 CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
327 if (ret != DISP_CHANGE_SUCCESSFUL)
328 return FALSE;
330 ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
331 return ret == DISP_CHANGE_SUCCESSFUL;
334 static HRESULT set_display_mode(IDirectDraw2 *ddraw, DWORD width, DWORD height)
336 if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
337 return DD_OK;
338 return IDirectDraw2_SetDisplayMode(ddraw, width, height, 24, 0, 0);
341 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
343 RECT rect = {x, y, x + 1, y + 1};
344 DDSURFACEDESC surface_desc;
345 D3DCOLOR color;
346 HRESULT hr;
348 memset(&surface_desc, 0, sizeof(surface_desc));
349 surface_desc.dwSize = sizeof(surface_desc);
351 hr = IDirectDrawSurface_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
352 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
353 if (FAILED(hr))
354 return 0xdeadbeef;
356 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
358 hr = IDirectDrawSurface_Unlock(surface, NULL);
359 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
361 return color;
364 static void fill_surface(IDirectDrawSurface *surface, D3DCOLOR color)
366 DDSURFACEDESC surface_desc = {sizeof(surface_desc)};
367 HRESULT hr;
368 unsigned int x, y;
369 DWORD *ptr;
371 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
372 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
374 for (y = 0; y < surface_desc.dwHeight; ++y)
376 ptr = (DWORD *)((BYTE *)surface_desc.lpSurface + y * surface_desc.lPitch);
377 for (x = 0; x < surface_desc.dwWidth; ++x)
379 ptr[x] = color;
383 hr = IDirectDrawSurface_Unlock(surface, NULL);
384 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
387 static void check_rect(IDirectDrawSurface *surface, RECT r)
389 LONG x_coords[2][2] =
391 {r.left - 1, r.left + 1},
392 {r.right + 1, r.right - 1},
394 LONG y_coords[2][2] =
396 {r.top - 1, r.top + 1},
397 {r.bottom + 1, r.bottom - 1}
399 unsigned int i, j, x_side, y_side, color;
400 LONG x, y;
402 for (i = 0; i < 2; ++i)
404 for (j = 0; j < 2; ++j)
406 for (x_side = 0; x_side < 2; ++x_side)
408 for (y_side = 0; y_side < 2; ++y_side)
410 unsigned int expected = (x_side == 1 && y_side == 1) ? 0x00ffffff : 0x00000000;
412 x = x_coords[i][x_side];
413 y = y_coords[j][y_side];
414 if (x < 0 || x >= 640 || y < 0 || y >= 480)
415 continue;
416 color = get_surface_color(surface, x, y);
417 ok(color == expected, "Pixel (%ld, %ld) has color %08x, expected %08x.\n", x, y, color, expected);
424 static DWORD get_device_z_depth(IDirect3DDevice2 *device)
426 DDSCAPS caps = {DDSCAPS_ZBUFFER};
427 IDirectDrawSurface *ds, *rt;
428 DDSURFACEDESC desc;
429 HRESULT hr;
431 if (FAILED(IDirect3DDevice2_GetRenderTarget(device, &rt)))
432 return 0;
434 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ds);
435 IDirectDrawSurface_Release(rt);
436 if (FAILED(hr))
437 return 0;
439 desc.dwSize = sizeof(desc);
440 hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
441 IDirectDrawSurface_Release(ds);
442 if (FAILED(hr))
443 return 0;
445 return desc.dwZBufferBitDepth;
448 static IDirectDraw2 *create_ddraw(void)
450 IDirectDraw2 *ddraw2;
451 IDirectDraw *ddraw1;
452 HRESULT hr;
454 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
455 return NULL;
457 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2);
458 IDirectDraw_Release(ddraw1);
459 if (FAILED(hr))
460 return NULL;
462 return ddraw2;
465 static IDirect3DDevice2 *create_device_ex(IDirectDraw2 *ddraw, HWND window, DWORD coop_level, const GUID *device_guid,
466 IDirectDrawSurface **ret_surface)
468 /* Prefer 16 bit depth buffers because Nvidia gives us an unpadded D24 buffer if we ask
469 * for 24 bit and handles such buffers incorrectly in DDBLT_DEPTHFILL. AMD only supports
470 * 16 bit buffers in ddraw1/2. Stencil was added in ddraw4, so we cannot create a D24S8
471 * buffer here. */
472 static const DWORD z_depths[] = {16, 32, 24};
473 IDirectDrawSurface *surface, *ds;
474 IDirect3DDevice2 *device = NULL;
475 DDSURFACEDESC surface_desc;
476 IDirect3D2 *d3d;
477 unsigned int i;
478 HRESULT hr;
480 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, coop_level);
481 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
483 memset(&surface_desc, 0, sizeof(surface_desc));
484 surface_desc.dwSize = sizeof(surface_desc);
485 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
486 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
487 if (is_software_device_type(device_guid))
488 surface_desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
489 surface_desc.dwWidth = 640;
490 surface_desc.dwHeight = 480;
492 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
493 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
495 if (coop_level & DDSCL_NORMAL)
497 IDirectDrawClipper *clipper;
499 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
500 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
501 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
502 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
503 hr = IDirectDrawSurface_SetClipper(surface, clipper);
504 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#lx.\n", hr);
505 IDirectDrawClipper_Release(clipper);
508 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
509 if (FAILED(hr))
511 IDirectDrawSurface_Release(surface);
512 return NULL;
515 /* We used to use EnumDevices() for this, but it seems
516 * D3DDEVICEDESC.dwDeviceZBufferBitDepth only has a very casual
517 * relationship with reality. */
518 for (i = 0; i < ARRAY_SIZE(z_depths); ++i)
520 memset(&surface_desc, 0, sizeof(surface_desc));
521 surface_desc.dwSize = sizeof(surface_desc);
522 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
523 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
524 if (is_software_device_type(device_guid))
525 surface_desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
526 surface_desc.dwZBufferBitDepth = z_depths[i];
527 surface_desc.dwWidth = 640;
528 surface_desc.dwHeight = 480;
529 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL)))
530 continue;
532 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
533 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#lx.\n", hr);
534 IDirectDrawSurface_Release(ds);
535 if (FAILED(hr))
536 continue;
538 if (SUCCEEDED(IDirect3D2_CreateDevice(d3d, device_guid, surface, &device)))
539 break;
541 IDirectDrawSurface_DeleteAttachedSurface(surface, 0, ds);
544 IDirect3D2_Release(d3d);
545 if (ret_surface)
546 *ret_surface = surface;
547 else
548 IDirectDrawSurface_Release(surface);
550 return device;
553 static IDirect3DDevice2 *create_device(IDirectDraw2 *ddraw, HWND window, DWORD coop_level)
555 return create_device_ex(ddraw, window, coop_level, &IID_IDirect3DHALDevice, NULL);
558 static IDirect3DViewport2 *create_viewport(IDirect3DDevice2 *device, UINT x, UINT y, UINT w, UINT h)
560 IDirect3DViewport2 *viewport;
561 D3DVIEWPORT2 vp;
562 IDirect3D2 *d3d;
563 HRESULT hr;
565 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
566 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
567 hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
568 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#lx.\n", hr);
569 hr = IDirect3DDevice2_AddViewport(device, viewport);
570 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#lx.\n", hr);
571 memset(&vp, 0, sizeof(vp));
572 vp.dwSize = sizeof(vp);
573 vp.dwX = x;
574 vp.dwY = y;
575 vp.dwWidth = w;
576 vp.dwHeight = h;
577 vp.dvClipX = -1.0f;
578 vp.dvClipY = 1.0f;
579 vp.dvClipWidth = 2.0f;
580 vp.dvClipHeight = 2.0f;
581 vp.dvMinZ = 0.0f;
582 vp.dvMaxZ = 1.0f;
583 hr = IDirect3DViewport2_SetViewport2(viewport, &vp);
584 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#lx.\n", hr);
585 IDirect3D2_Release(d3d);
587 return viewport;
590 static void viewport_set_background(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport,
591 IDirect3DMaterial2 *material)
593 D3DMATERIALHANDLE material_handle;
594 HRESULT hr;
596 hr = IDirect3DMaterial2_GetHandle(material, device, &material_handle);
597 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#lx.\n", hr);
598 hr = IDirect3DViewport2_SetBackground(viewport, material_handle);
599 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#lx.\n", hr);
602 static void destroy_viewport(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport)
604 HRESULT hr;
606 hr = IDirect3DDevice2_DeleteViewport(device, viewport);
607 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#lx.\n", hr);
608 IDirect3DViewport2_Release(viewport);
611 static IDirect3DMaterial2 *create_material(IDirect3DDevice2 *device, D3DMATERIAL *mat)
613 IDirect3DMaterial2 *material;
614 IDirect3D2 *d3d;
615 HRESULT hr;
617 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
618 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
619 hr = IDirect3D2_CreateMaterial(d3d, &material, NULL);
620 ok(SUCCEEDED(hr), "Failed to create material, hr %#lx.\n", hr);
621 hr = IDirect3DMaterial2_SetMaterial(material, mat);
622 ok(SUCCEEDED(hr), "Failed to set material data, hr %#lx.\n", hr);
623 IDirect3D2_Release(d3d);
625 return material;
628 static IDirect3DMaterial2 *create_diffuse_material(IDirect3DDevice2 *device, float r, float g, float b, float a)
630 D3DMATERIAL mat;
632 memset(&mat, 0, sizeof(mat));
633 mat.dwSize = sizeof(mat);
634 mat.diffuse.r = r;
635 mat.diffuse.g = g;
636 mat.diffuse.b = b;
637 mat.diffuse.a = a;
639 return create_material(device, &mat);
642 static IDirect3DMaterial2 *create_diffuse_and_ambient_material(IDirect3DDevice2 *device,
643 float r, float g, float b, float a)
645 D3DMATERIAL mat;
647 memset(&mat, 0, sizeof(mat));
648 mat.dwSize = sizeof(mat);
649 mat.diffuse.r = r;
650 mat.diffuse.g = g;
651 mat.diffuse.b = b;
652 mat.diffuse.a = a;
654 mat.ambient.r = r;
655 mat.ambient.g = g;
656 mat.ambient.b = b;
657 mat.ambient.a = a;
659 return create_material(device, &mat);
662 static IDirect3DMaterial2 *create_specular_material(IDirect3DDevice2 *device,
663 float r, float g, float b, float a, float power)
665 D3DMATERIAL mat;
667 memset(&mat, 0, sizeof(mat));
668 mat.dwSize = sizeof(mat);
669 mat.specular.r = r;
670 mat.specular.g = g;
671 mat.specular.b = b;
672 mat.specular.a = a;
673 mat.power = power;
675 return create_material(device, &mat);
678 static IDirect3DMaterial2 *create_emissive_material(IDirect3DDevice2 *device, float r, float g, float b, float a)
680 D3DMATERIAL mat;
682 memset(&mat, 0, sizeof(mat));
683 mat.dwSize = sizeof(mat);
684 mat.emissive.r = r;
685 mat.emissive.g = g;
686 mat.emissive.b = b;
687 mat.emissive.a = a;
689 return create_material(device, &mat);
692 static void destroy_material(IDirect3DMaterial2 *material)
694 IDirect3DMaterial2_Release(material);
697 struct message
699 UINT message;
700 BOOL check_wparam;
701 WPARAM expect_wparam;
704 static const struct message *expect_messages;
706 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
708 if (expect_messages && message == expect_messages->message)
710 if (expect_messages->check_wparam)
711 ok (wparam == expect_messages->expect_wparam,
712 "Got unexpected wparam %#Ix for message %#x, expected %#Ix.\n",
713 wparam, message, expect_messages->expect_wparam);
715 ++expect_messages;
718 return DefWindowProcA(hwnd, message, wparam, lparam);
721 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
722 * interface. This prevents subsequent SetCooperativeLevel() calls on a
723 * different window from failing with DDERR_HWNDALREADYSET. */
724 static void fix_wndproc(HWND window, LONG_PTR proc)
726 IDirectDraw2 *ddraw;
727 HRESULT hr;
729 if (!(ddraw = create_ddraw()))
730 return;
732 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
733 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
734 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
735 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
736 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
738 IDirectDraw2_Release(ddraw);
741 static HRESULT CALLBACK restore_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
743 HRESULT hr = IDirectDrawSurface_Restore(surface);
744 ok(SUCCEEDED(hr) || hr == DDERR_IMPLICITLYCREATED, "Failed to restore surface, hr %#lx.\n", hr);
745 IDirectDrawSurface_Release(surface);
747 return DDENUMRET_OK;
750 static HRESULT restore_surfaces(IDirectDraw2 *ddraw)
752 return IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
753 NULL, NULL, restore_callback);
756 static void test_coop_level_create_device_window(void)
758 HWND focus_window, device_window;
759 IDirectDraw2 *ddraw;
760 HRESULT hr;
762 focus_window = create_window();
763 ddraw = create_ddraw();
764 ok(!!ddraw, "Failed to create a ddraw object.\n");
766 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
767 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
768 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
769 ok(!device_window, "Unexpected device window found.\n");
770 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
771 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
772 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
773 ok(!device_window, "Unexpected device window found.\n");
774 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
775 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
776 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
777 ok(!device_window, "Unexpected device window found.\n");
778 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
779 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
780 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
781 ok(!device_window, "Unexpected device window found.\n");
782 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
783 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#lx.\n", hr);
784 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
785 ok(!device_window, "Unexpected device window found.\n");
787 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
788 if (broken(hr == DDERR_INVALIDPARAMS))
790 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
791 IDirectDraw2_Release(ddraw);
792 DestroyWindow(focus_window);
793 return;
796 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
797 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
798 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
799 ok(!device_window, "Unexpected device window found.\n");
800 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
801 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
802 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
803 ok(!device_window, "Unexpected device window found.\n");
805 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
806 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
807 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
808 ok(!device_window, "Unexpected device window found.\n");
809 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
810 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
811 ok(hr == DDERR_NOHWND, "Got unexpected hr %#lx.\n", hr);
812 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
813 ok(!!device_window, "Device window not found.\n");
815 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
816 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
817 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
818 ok(!device_window, "Unexpected device window found.\n");
819 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
820 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
821 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
822 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
823 ok(!!device_window, "Device window not found.\n");
825 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
826 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
827 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
828 ok(!device_window, "Unexpected device window found.\n");
829 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
830 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#lx.\n", hr);
831 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
832 ok(!device_window, "Unexpected device window found.\n");
833 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
834 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
835 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
836 ok(!device_window, "Unexpected device window found.\n");
837 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
838 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
839 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
840 ok(!!device_window, "Device window not found.\n");
842 IDirectDraw2_Release(ddraw);
843 DestroyWindow(focus_window);
846 static void test_clipper_blt(void)
848 IDirectDrawSurface *src_surface, *dst_surface;
849 unsigned int color, i, j, x, y;
850 RECT client_rect, src_rect;
851 IDirectDrawClipper *clipper;
852 DDSURFACEDESC surface_desc;
853 IDirectDraw2 *ddraw;
854 RGNDATA *rgn_data;
855 ULONG refcount;
856 HRGN r1, r2;
857 HWND window;
858 DDBLTFX fx;
859 HRESULT hr;
860 DWORD *ptr;
861 DWORD ret;
863 static const DWORD src_data[] =
865 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
866 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
867 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
869 static const unsigned int expected1[] =
871 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
872 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
873 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
874 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
876 /* Nvidia on Windows seems to have an off-by-one error
877 * when processing source rectangles. Our left = 1 and
878 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
879 * read as well, but only for the edge pixels on the
880 * output image. The bug happens on the y axis as well,
881 * but we only read one row there, and all source rows
882 * contain the same data. This bug is not dependent on
883 * the presence of a clipper. */
884 static const D3DCOLOR expected1_broken[] =
886 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
887 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
888 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
889 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
891 static const unsigned int expected2[] =
893 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
894 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
895 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
896 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
899 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
900 10, 10, 640, 480, 0, 0, 0, 0);
901 ShowWindow(window, SW_SHOW);
902 ddraw = create_ddraw();
903 ok(!!ddraw, "Failed to create a ddraw object.\n");
905 ret = GetClientRect(window, &client_rect);
906 ok(ret, "Failed to get client rect.\n");
907 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
908 ok(ret, "Failed to map client rect.\n");
910 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
911 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
913 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
914 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
915 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
916 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#lx.\n", hr);
917 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
918 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
919 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
920 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#lx.\n", hr);
921 rgn_data = malloc(ret);
922 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
923 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#lx.\n", hr);
924 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#lx.\n", rgn_data->rdh.dwSize);
925 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#lx.\n", rgn_data->rdh.iType);
926 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %lu.\n", rgn_data->rdh.nCount);
927 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
928 "Got unexpected bounding rect %s, expected %s.\n",
929 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
930 free(rgn_data);
932 r1 = CreateRectRgn(0, 0, 320, 240);
933 ok(!!r1, "Failed to create region.\n");
934 r2 = CreateRectRgn(320, 240, 640, 480);
935 ok(!!r2, "Failed to create region.\n");
936 CombineRgn(r1, r1, r2, RGN_OR);
937 ret = GetRegionData(r1, 0, NULL);
938 rgn_data = malloc(ret);
939 ret = GetRegionData(r1, ret, rgn_data);
940 ok(!!ret, "Failed to get region data.\n");
942 DeleteObject(r2);
943 DeleteObject(r1);
945 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
946 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#lx.\n", hr);
947 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
948 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
949 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
950 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#lx.\n", hr);
952 free(rgn_data);
954 memset(&surface_desc, 0, sizeof(surface_desc));
955 surface_desc.dwSize = sizeof(surface_desc);
956 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
957 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
958 surface_desc.dwWidth = 640;
959 surface_desc.dwHeight = 480;
960 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
961 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
962 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
963 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
964 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
965 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
967 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
968 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#lx.\n", hr);
969 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
970 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#lx.\n", hr);
972 memset(&fx, 0, sizeof(fx));
973 fx.dwSize = sizeof(fx);
974 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
975 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#lx.\n", hr);
976 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
977 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#lx.\n", hr);
979 hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
980 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#lx.\n", hr);
981 ok(surface_desc.lPitch == 2560, "Got unexpected surface pitch %lu.\n", surface_desc.lPitch);
982 ptr = surface_desc.lpSurface;
983 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
984 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
985 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
986 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
987 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#lx.\n", hr);
989 hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
990 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
992 SetRect(&src_rect, 1, 1, 5, 2);
993 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
994 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
995 for (i = 0; i < 4; ++i)
997 for (j = 0; j < 4; ++j)
999 x = 80 * ((2 * j) + 1);
1000 y = 60 * ((2 * i) + 1);
1001 color = get_surface_color(dst_surface, x, y);
1002 ok(compare_color(color, expected1[i * 4 + j], 1)
1003 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
1004 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
1008 fx.dwFillColor = 0xff0000ff;
1009 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1010 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#lx.\n", hr);
1011 for (i = 0; i < 4; ++i)
1013 for (j = 0; j < 4; ++j)
1015 x = 80 * ((2 * j) + 1);
1016 y = 60 * ((2 * i) + 1);
1017 color = get_surface_color(dst_surface, x, y);
1018 ok(compare_color(color, expected2[i * 4 + j], 1),
1019 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
1023 hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
1024 ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#lx.\n", hr);
1026 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
1027 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
1028 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1029 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#lx.\n", hr);
1030 DestroyWindow(window);
1031 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1032 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
1033 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
1034 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
1035 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1036 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#lx.\n", hr);
1037 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
1038 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#lx.\n", hr);
1039 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1040 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#lx.\n", hr);
1041 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1042 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#lx.\n", hr);
1044 IDirectDrawSurface_Release(dst_surface);
1045 IDirectDrawSurface_Release(src_surface);
1046 refcount = IDirectDrawClipper_Release(clipper);
1047 ok(!refcount, "Clipper has %lu references left.\n", refcount);
1048 IDirectDraw2_Release(ddraw);
1051 static void test_coop_level_d3d_state(void)
1053 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1054 IDirectDrawSurface *rt, *surface;
1055 IDirect3DMaterial2 *background;
1056 IDirect3DViewport2 *viewport;
1057 IDirect3DDevice2 *device;
1058 D3DMATERIAL material;
1059 IDirectDraw2 *ddraw;
1060 DDSURFACEDESC lock;
1061 unsigned int color;
1062 DWORD value;
1063 HWND window;
1064 HRESULT hr;
1066 static D3DLVERTEX quad[] =
1068 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0x800000ff}},
1069 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0x800000ff}},
1070 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0x800000ff}},
1071 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0x800000ff}},
1074 window = create_window();
1075 ddraw = create_ddraw();
1076 ok(!!ddraw, "Failed to create a ddraw object.\n");
1078 if (ddraw_is_warp(ddraw))
1080 /* ddraw2 crashes in EndScene, and if it doesn't crash it fails with
1081 * DDERR_SURFACELOST on WARP. */
1082 win_skip("Skipping test that crashes WARP occasionally.\n");
1083 IDirectDraw2_Release(ddraw);
1084 DestroyWindow(window);
1085 return;
1088 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1090 skip("Failed to create a 3D device, skipping test.\n");
1091 IDirectDraw2_Release(ddraw);
1092 DestroyWindow(window);
1093 return;
1096 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1097 viewport = create_viewport(device, 0, 0, 640, 480);
1098 viewport_set_background(device, viewport, background);
1100 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1101 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1102 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
1103 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1105 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1106 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1107 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1108 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1109 ok(!!value, "Got unexpected z-enable state %#lx.\n", value);
1110 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1111 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1112 ok(!value, "Got unexpected alpha blend enable state %#lx.\n", value);
1113 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
1114 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1115 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1116 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1117 color = get_surface_color(rt, 320, 240);
1118 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1120 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1121 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1122 hr = IDirectDrawSurface_IsLost(rt);
1123 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
1125 memset(&lock, 0, sizeof(lock));
1126 lock.dwSize = sizeof(lock);
1127 lock.lpSurface = (void *)0xdeadbeef;
1128 hr = IDirectDrawSurface2_Lock(rt, NULL, &lock, DDLOCK_READONLY, NULL);
1129 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
1130 ok(lock.lpSurface == (void *)0xdeadbeef, "Got unexpected lock.lpSurface %p.\n", lock.lpSurface);
1132 hr = restore_surfaces(ddraw);
1133 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1135 hr = IDirectDrawSurface2_Lock(rt, NULL, &lock, DDLOCK_READONLY, NULL);
1136 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1137 hr = IDirectDrawSurface2_Unlock(rt, NULL);
1138 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1140 memset(&material, 0, sizeof(material));
1141 material.dwSize = sizeof(material);
1142 material.diffuse.r = 0.0f;
1143 material.diffuse.g = 1.0f;
1144 material.diffuse.b = 0.0f;
1145 material.diffuse.a = 1.0f;
1146 hr = IDirect3DMaterial2_SetMaterial(background, &material);
1147 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1149 hr = IDirect3DDevice2_GetRenderTarget(device, &surface);
1150 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1151 ok(surface == rt, "Got unexpected surface %p.\n", surface);
1152 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1153 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1154 ok(!!value, "Got unexpected z-enable state %#lx.\n", value);
1155 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1156 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1157 ok(!!value, "Got unexpected alpha blend enable state %#lx.\n", value);
1158 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1159 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1160 color = get_surface_color(rt, 320, 240);
1161 ok(compare_color(color, 0x0000ff00, 1) || broken(compare_color(color, 0x00000000, 1)),
1162 "Got unexpected color 0x%08x.\n", color);
1164 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1165 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1166 hr = IDirect3DDevice2_BeginScene(device);
1167 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1168 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, ARRAY_SIZE(quad), 0);
1169 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1170 hr = IDirect3DDevice2_EndScene(device);
1171 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1172 color = get_surface_color(rt, 320, 240);
1173 ok(compare_color(color, 0x0000ff80, 1), "Got unexpected color 0x%08x.\n", color);
1175 destroy_viewport(device, viewport);
1176 destroy_material(background);
1177 IDirectDrawSurface_Release(surface);
1178 IDirectDrawSurface_Release(rt);
1179 IDirect3DDevice2_Release(device);
1180 IDirectDraw2_Release(ddraw);
1181 DestroyWindow(window);
1184 static void test_surface_interface_mismatch(void)
1186 IDirectDraw2 *ddraw = NULL;
1187 IDirect3D2 *d3d = NULL;
1188 IDirectDrawSurface *surface = NULL, *ds;
1189 IDirectDrawSurface3 *surface3 = NULL;
1190 IDirect3DDevice2 *device = NULL;
1191 IDirect3DViewport2 *viewport = NULL;
1192 IDirect3DMaterial2 *background = NULL;
1193 DDSURFACEDESC surface_desc;
1194 unsigned int color;
1195 DWORD z_depth = 0;
1196 ULONG refcount;
1197 HRESULT hr;
1198 HWND window;
1199 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1201 window = create_window();
1202 ddraw = create_ddraw();
1203 ok(!!ddraw, "Failed to create a ddraw object.\n");
1204 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1206 skip("Failed to create a 3D device, skipping test.\n");
1207 IDirectDraw2_Release(ddraw);
1208 DestroyWindow(window);
1209 return;
1211 z_depth = get_device_z_depth(device);
1212 ok(!!z_depth, "Failed to get device z depth.\n");
1213 IDirect3DDevice2_Release(device);
1214 device = NULL;
1216 memset(&surface_desc, 0, sizeof(surface_desc));
1217 surface_desc.dwSize = sizeof(surface_desc);
1218 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1219 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1220 surface_desc.dwWidth = 640;
1221 surface_desc.dwHeight = 480;
1223 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1224 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
1226 hr = IDirectDrawSurface2_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1227 if (FAILED(hr))
1229 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
1230 goto cleanup;
1233 if (FAILED(IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
1235 skip("D3D interface is not available, skipping test.\n");
1236 goto cleanup;
1239 memset(&surface_desc, 0, sizeof(surface_desc));
1240 surface_desc.dwSize = sizeof(surface_desc);
1241 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
1242 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1243 surface_desc.dwZBufferBitDepth = z_depth;
1244 surface_desc.dwWidth = 640;
1245 surface_desc.dwHeight = 480;
1246 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1247 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#lx.\n", hr);
1248 if (FAILED(hr))
1249 goto cleanup;
1251 /* Using a different surface interface version still works */
1252 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1253 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#lx.\n", hr);
1254 refcount = IDirectDrawSurface_Release(ds);
1255 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
1256 if (FAILED(hr))
1257 goto cleanup;
1259 /* Here too */
1260 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface *)surface3, &device);
1261 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1262 if (FAILED(hr))
1263 goto cleanup;
1265 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1266 viewport = create_viewport(device, 0, 0, 640, 480);
1267 viewport_set_background(device, viewport, background);
1269 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1270 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
1271 color = get_surface_color(surface, 320, 240);
1272 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1274 cleanup:
1275 if (viewport)
1276 destroy_viewport(device, viewport);
1277 if (background)
1278 destroy_material(background);
1279 if (surface3) IDirectDrawSurface3_Release(surface3);
1280 if (surface) IDirectDrawSurface_Release(surface);
1281 if (device) IDirect3DDevice2_Release(device);
1282 if (d3d) IDirect3D2_Release(d3d);
1283 if (ddraw) IDirectDraw2_Release(ddraw);
1284 DestroyWindow(window);
1287 static void test_coop_level_threaded(void)
1289 struct create_window_thread_param p;
1290 IDirectDraw2 *ddraw;
1291 HRESULT hr;
1293 ddraw = create_ddraw();
1294 ok(!!ddraw, "Failed to create a ddraw object.\n");
1295 create_window_thread(&p);
1297 hr = IDirectDraw2_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1298 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
1300 destroy_window_thread(&p);
1301 IDirectDraw2_Release(ddraw);
1304 static void test_depth_blit(const GUID *device_guid)
1306 static D3DLVERTEX quad1[] =
1308 {{-1.0}, { 1.0}, {0.50f}, 0, {0xff00ff00}},
1309 {{ 1.0}, { 1.0}, {0.50f}, 0, {0xff00ff00}},
1310 {{-1.0}, {-1.0}, {0.50f}, 0, {0xff00ff00}},
1311 {{ 1.0}, {-1.0}, {0.50f}, 0, {0xff00ff00}},
1313 static const unsigned int expected_colors[4][4] =
1315 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1316 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1317 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1318 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1320 DDSURFACEDESC ddsd_new, ddsd_existing;
1322 IDirect3DDevice2 *device;
1323 IDirectDrawSurface *ds1, *ds2, *ds3, *rt;
1324 BOOL depth_fill_broken = FALSE;
1325 IDirect3DViewport2 *viewport;
1326 RECT src_rect, dst_rect;
1327 unsigned int color, i, j;
1328 HRESULT hr;
1329 IDirectDraw2 *ddraw;
1330 DDBLTFX fx;
1331 HWND window;
1332 D3DRECT d3drect;
1333 IDirect3DMaterial2 *background;
1335 window = create_window();
1336 ddraw = create_ddraw();
1337 ok(!!ddraw, "Failed to create a ddraw object.\n");
1338 if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid, NULL)))
1340 skip("Failed to create a 3D device, skipping test.\n");
1341 IDirectDraw2_Release(ddraw);
1342 DestroyWindow(window);
1343 return;
1346 ds1 = get_depth_stencil(device);
1348 memset(&ddsd_new, 0, sizeof(ddsd_new));
1349 ddsd_new.dwSize = sizeof(ddsd_new);
1350 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1351 ddsd_existing.dwSize = sizeof(ddsd_existing);
1352 hr = IDirectDrawSurface_GetSurfaceDesc(ds1, &ddsd_existing);
1353 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1354 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1355 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1356 if (is_software_device_type(device_guid))
1357 ddsd_new.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
1358 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1359 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1360 ddsd_new.ddpfPixelFormat = ddsd_existing.ddpfPixelFormat;
1361 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1362 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#lx.\n", hr);
1363 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1364 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#lx.\n", hr);
1366 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1367 viewport = create_viewport(device, 0, 0, ddsd_existing.dwWidth, ddsd_existing.dwHeight);
1368 viewport_set_background(device, viewport, background);
1369 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1370 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#lx.\n", hr);
1372 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1373 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#lx.\n", hr);
1374 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1375 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#lx.\n", hr);
1377 d3drect.x1 = d3drect.y1 = 0;
1378 d3drect.x2 = ddsd_existing.dwWidth; d3drect.y2 = ddsd_existing.dwHeight;
1379 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER);
1380 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#lx.\n", hr);
1382 /* Partial blit. */
1383 SetRect(&src_rect, 0, 0, 320, 240);
1384 SetRect(&dst_rect, 0, 0, 320, 240);
1385 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1386 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1387 /* Different locations. */
1388 SetRect(&src_rect, 0, 0, 320, 240);
1389 SetRect(&dst_rect, 320, 240, 640, 480);
1390 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1391 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1392 /* Stretched. */
1393 SetRect(&src_rect, 0, 0, 320, 240);
1394 SetRect(&dst_rect, 0, 0, 640, 480);
1395 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1396 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1397 /* Flipped. */
1398 SetRect(&src_rect, 0, 480, 640, 0);
1399 SetRect(&dst_rect, 0, 0, 640, 480);
1400 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1401 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
1402 SetRect(&src_rect, 0, 0, 640, 480);
1403 SetRect(&dst_rect, 0, 480, 640, 0);
1404 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1405 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
1406 /* Full, explicit. */
1407 SetRect(&src_rect, 0, 0, 640, 480);
1408 SetRect(&dst_rect, 0, 0, 640, 480);
1409 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1410 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1411 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1413 /* Depth blit inside a BeginScene / EndScene pair */
1414 hr = IDirect3DDevice2_BeginScene(device);
1415 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#lx.\n", hr);
1416 /* From the current depth stencil */
1417 hr = IDirectDrawSurface_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1418 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1419 /* To the current depth stencil */
1420 hr = IDirectDrawSurface_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1421 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1422 /* Between unbound surfaces */
1423 hr = IDirectDrawSurface_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1424 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1425 hr = IDirect3DDevice2_EndScene(device);
1426 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#lx.\n", hr);
1428 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1429 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1430 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1431 * a reliable result(z = 0.0) */
1432 memset(&fx, 0, sizeof(fx));
1433 fx.dwSize = sizeof(fx);
1434 fx.dwFillDepth = 0;
1435 hr = IDirectDrawSurface_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1436 ok(hr == D3D_OK || broken(is_software_device_type(device_guid)
1437 && hr == 0x8876086c /* D3DERR_INVALIDCALL */), "Got unexpected hr %#lx.\n", hr);
1438 if (hr != D3D_OK)
1439 depth_fill_broken = TRUE;
1441 /* This clears the Z buffer with 1.0 */
1442 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET);
1443 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1445 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1446 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1448 color = get_surface_color(rt, 80, 60);
1449 /* For some reason clears and colour fill blits randomly fail with software render target. */
1450 ok(color == 0x00ff0000 || broken(is_software_device_type(device_guid) && !color),
1451 "Got unexpected colour 0x%08x.\n", color);
1452 if (!color)
1454 fill_surface(rt, 0xffff0000);
1456 color = get_surface_color(rt, 80, 60);
1457 ok(color == 0x00ff0000, "Got unexpected colour 0x%08x.\n", color);
1460 SetRect(&dst_rect, 0, 0, 320, 240);
1461 hr = IDirectDrawSurface_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1462 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1463 IDirectDrawSurface_Release(ds3);
1464 IDirectDrawSurface_Release(ds2);
1465 IDirectDrawSurface_Release(ds1);
1467 hr = IDirect3DDevice2_BeginScene(device);
1468 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1469 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad1, 4, 0);
1470 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1471 hr = IDirect3DDevice2_EndScene(device);
1472 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1474 for (i = 0; i < 4; ++i)
1476 for (j = 0; j < 4; ++j)
1478 unsigned int x = 80 * ((2 * j) + 1);
1479 unsigned int y = 60 * ((2 * i) + 1);
1480 color = get_surface_color(rt, x, y);
1481 ok(compare_color(color, expected_colors[i][j], 1) || broken(depth_fill_broken && color == 0x0000ff00),
1482 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1485 IDirectDrawSurface_Release(rt);
1487 destroy_viewport(device, viewport);
1488 destroy_material(background);
1489 IDirect3DDevice2_Release(device);
1490 IDirectDraw2_Release(ddraw);
1491 DestroyWindow(window);
1494 static void test_texture_load_ckey(void)
1496 IDirectDraw2 *ddraw = NULL;
1497 IDirectDrawSurface *src = NULL;
1498 IDirectDrawSurface *dst = NULL;
1499 IDirect3DTexture *src_tex = NULL;
1500 IDirect3DTexture *dst_tex = NULL;
1501 DDSURFACEDESC ddsd;
1502 HRESULT hr;
1503 DDCOLORKEY ckey;
1505 ddraw = create_ddraw();
1506 ok(!!ddraw, "Failed to create a ddraw object.\n");
1507 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1508 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
1510 memset(&ddsd, 0, sizeof(ddsd));
1511 ddsd.dwSize = sizeof(ddsd);
1512 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1513 ddsd.dwHeight = 128;
1514 ddsd.dwWidth = 128;
1515 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1516 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &src, NULL);
1517 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#lx.\n", hr);
1518 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1519 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &dst, NULL);
1520 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#lx.\n", hr);
1522 hr = IDirectDrawSurface_QueryInterface(src, &IID_IDirect3DTexture, (void **)&src_tex);
1523 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture interface, hr %#lx.\n", hr);
1524 if (FAILED(hr))
1526 /* 64 bit ddraw does not support d3d */
1527 skip("Could not get Direct3DTexture interface, skipping texture::Load color keying tests.\n");
1528 goto done;
1530 hr = IDirectDrawSurface_QueryInterface(dst, &IID_IDirect3DTexture, (void **)&dst_tex);
1531 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture interface, hr %#lx.\n", hr);
1533 /* No surface has a color key */
1534 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1535 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDCAPS), "Got unexpected hr %#lx.\n", hr);
1536 if (FAILED(hr))
1538 /* Testbot Windows NT VMs */
1539 skip("IDirect3DTexture::Load does not work, skipping color keying tests.\n");
1540 goto done;
1543 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1544 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1545 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx.\n", hr);
1546 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
1547 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
1549 /* Source surface has a color key */
1550 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1551 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1552 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
1553 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1554 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1555 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1556 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1557 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
1558 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
1560 /* Both surfaces have a color key: Dest ckey is overwritten */
1561 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1562 hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1563 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
1564 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1565 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1566 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1567 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1568 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
1569 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
1571 /* Only the destination has a color key: It is not deleted */
1572 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1573 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
1574 hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1575 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx.\n", hr);
1576 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1577 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1578 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1579 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1580 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
1581 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
1583 done:
1584 if (dst_tex) IDirect3DTexture_Release(dst_tex);
1585 if (src_tex) IDirect3DTexture_Release(src_tex);
1586 if (dst) IDirectDrawSurface_Release(dst);
1587 if (src) IDirectDrawSurface_Release(src);
1588 if (ddraw) IDirectDraw2_Release(ddraw);
1591 static BOOL compare_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
1593 return mode1->dmPosition.x == mode2->dmPosition.x
1594 && mode1->dmPosition.y == mode2->dmPosition.y
1595 && mode1->dmPelsWidth == mode2->dmPelsWidth
1596 && mode1->dmPelsHeight == mode2->dmPelsHeight;
1599 static ULONG get_refcount(IUnknown *test_iface)
1601 IUnknown_AddRef(test_iface);
1602 return IUnknown_Release(test_iface);
1605 static void test_viewport_object(void)
1607 IDirectDraw2 *ddraw;
1608 IDirect3D2 *d3d;
1609 HRESULT hr;
1610 ULONG ref, old_d3d_ref;
1611 D3DVIEWPORT vp;
1612 D3DVIEWPORT2 vp2;
1613 IDirect3DViewport *viewport;
1614 IDirect3DViewport2 *viewport2, *another_vp, *test_vp;
1615 IDirect3DViewport3 *viewport3;
1616 IDirectDrawGammaControl *gamma;
1617 IUnknown *unknown;
1618 IDirect3DDevice2 *device;
1619 HWND window;
1620 union
1622 D3DVIEWPORT2 vp2;
1623 D3DVIEWPORT vp1;
1624 BYTE blob[1024];
1625 } desc;
1627 window = create_window();
1628 ddraw = create_ddraw();
1629 ok(!!ddraw, "Failed to create a ddraw object.\n");
1630 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1632 skip("Failed to create a 3D device, skipping test.\n");
1633 IDirectDraw2_Release(ddraw);
1634 DestroyWindow(window);
1635 return;
1638 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
1639 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get d3d interface, hr %#lx.\n", hr);
1640 if (FAILED(hr))
1642 skip("D3D interface is not available, skipping test.\n");
1643 IDirectDraw2_Release(ddraw);
1644 return;
1646 old_d3d_ref = get_refcount((IUnknown *)d3d);
1648 hr = IDirect3D2_CreateViewport(d3d, &viewport2, NULL);
1649 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#lx.\n", hr);
1650 ref = get_refcount((IUnknown *)viewport2);
1651 ok(ref == 1, "Got unexpected refcount %lu.\n", ref);
1652 ref = get_refcount((IUnknown *)d3d);
1653 ok(ref == old_d3d_ref, "Got unexpected refcount %lu.\n", ref);
1655 memset(&desc, 0, sizeof(desc));
1656 hr = IDirect3DViewport2_GetViewport(viewport2, &desc.vp1);
1657 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1658 desc.vp1.dwSize = sizeof(desc.vp1) + 1;
1659 hr = IDirect3DViewport2_GetViewport(viewport2, &desc.vp1);
1660 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1661 desc.vp1.dwSize = sizeof(desc.vp1) - 1;
1662 hr = IDirect3DViewport2_GetViewport(viewport2, &desc.vp1);
1663 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1664 desc.vp1.dwSize = sizeof(desc.vp1);
1665 hr = IDirect3DViewport2_GetViewport(viewport2, &desc.vp1);
1666 ok(hr == D3DERR_VIEWPORTDATANOTSET, "Got unexpected hr %#lx.\n", hr);
1667 ok(desc.vp1.dwSize == sizeof(desc.vp1), "Got unexpected dwSize %lu.\n", desc.vp1.dwSize);
1668 hr = IDirect3DViewport2_GetViewport2(viewport2, &desc.vp2);
1669 ok(hr == D3DERR_VIEWPORTDATANOTSET, "Got unexpected hr %#lx.\n", hr);
1670 ok(desc.vp2.dwSize == sizeof(desc.vp2), "Got unexpected dwSize %lu.\n", desc.vp2.dwSize);
1671 desc.vp2.dwSize = sizeof(desc.vp2) + 1;
1672 hr = IDirect3DViewport2_GetViewport2(viewport2, &desc.vp2);
1673 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1675 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1676 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirectDrawGammaControl, (void **)&gamma);
1677 ok(hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr);
1678 ok(!gamma, "Interface not set to NULL by failed QI call: %p\n", gamma);
1679 /* NULL iid: Segfaults */
1681 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport, (void **)&viewport);
1682 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#lx.\n", hr);
1683 ref = get_refcount((IUnknown *)viewport);
1684 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1685 ref = get_refcount((IUnknown *)viewport2);
1686 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1687 IDirect3DViewport_Release(viewport);
1688 viewport = NULL;
1690 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport3, (void **)&viewport3);
1691 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to QI IDirect3DViewport3, hr %#lx.\n", hr);
1692 if (viewport3)
1694 ref = get_refcount((IUnknown *)viewport2);
1695 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1696 ref = get_refcount((IUnknown *)viewport3);
1697 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1698 IDirect3DViewport3_Release(viewport3);
1701 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IUnknown, (void **)&unknown);
1702 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#lx.\n", hr);
1703 ref = get_refcount((IUnknown *)viewport2);
1704 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1705 ref = get_refcount(unknown);
1706 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1707 IUnknown_Release(unknown);
1709 hr = IDirect3DDevice2_DeleteViewport(device, NULL);
1710 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1711 hr = IDirect3DDevice2_GetCurrentViewport(device, NULL);
1712 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#lx.\n", hr);
1714 hr = IDirect3D2_CreateViewport(d3d, &another_vp, NULL);
1715 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#lx.\n", hr);
1717 /* Setting a viewport not in the viewport list fails */
1718 hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
1719 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1721 /* AddViewport(NULL): Segfault */
1722 hr = IDirect3DDevice2_AddViewport(device, viewport2);
1723 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#lx.\n", hr);
1724 ref = get_refcount((IUnknown *) viewport2);
1725 ok(ref == 2, "viewport2 refcount is %lu.\n", ref);
1726 hr = IDirect3DDevice2_AddViewport(device, another_vp);
1727 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#lx.\n", hr);
1728 ref = get_refcount((IUnknown *) another_vp);
1729 ok(ref == 2, "another_vp refcount is %lu.\n", ref);
1731 test_vp = (IDirect3DViewport2 *) 0xbaadc0de;
1732 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1733 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#lx.\n", hr);
1734 ok(test_vp == (IDirect3DViewport2 *) 0xbaadc0de, "Got unexpected pointer %p\n", test_vp);
1736 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
1737 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
1738 ref = get_refcount((IUnknown *) viewport2);
1739 ok(ref == 3, "Got unexpected refcount %lu.\n", ref);
1740 ref = get_refcount((IUnknown *) device);
1741 ok(ref == 1, "Got unexpected refcount %lu.\n", ref);
1743 test_vp = NULL;
1744 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1745 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1746 ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
1747 ref = get_refcount((IUnknown *) viewport2);
1748 ok(ref == 4, "Got unexpected refcount %lu.\n", ref);
1749 if (test_vp)
1750 IDirect3DViewport2_Release(test_vp);
1752 /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
1754 /* Cannot set the viewport to NULL */
1755 hr = IDirect3DDevice2_SetCurrentViewport(device, NULL);
1756 ok(hr == DDERR_INVALIDPARAMS, "Failed to set viewport to NULL, hr %#lx.\n", hr);
1757 test_vp = NULL;
1758 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1759 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1760 ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
1761 if (test_vp)
1762 IDirect3DViewport2_Release(test_vp);
1764 /* SetCurrentViewport properly releases the old viewport's reference */
1765 hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
1766 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
1767 ref = get_refcount((IUnknown *) viewport2);
1768 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1769 ref = get_refcount((IUnknown *) another_vp);
1770 ok(ref == 3, "Got unexpected refcount %lu.\n", ref);
1772 /* Deleting the viewport removes the reference added by AddViewport, but not
1773 * the one added by SetCurrentViewport. */
1774 hr = IDirect3DDevice2_DeleteViewport(device, another_vp);
1775 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#lx.\n", hr);
1776 ref = get_refcount((IUnknown *) another_vp);
1777 todo_wine ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1779 /* GetCurrentViewport fails though */
1780 test_vp = NULL;
1781 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1782 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#lx.\n", hr);
1783 ok(!test_vp, "Got unexpected viewport %p\n", test_vp);
1785 /* Setting a different viewport does not free the leaked reference. How
1786 * do I get rid of it? Leak the viewport for now. */
1787 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
1788 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
1789 ref = get_refcount((IUnknown *) viewport2);
1790 ok(ref == 3, "Got unexpected refcount %lu.\n", ref);
1791 ref = get_refcount((IUnknown *) another_vp);
1792 todo_wine ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1794 memset(&vp, 0, sizeof(vp));
1795 memset(&vp, 0, sizeof(vp2));
1796 vp.dwX = vp2.dwX = 0;
1797 vp.dwY = vp2.dwY = 0;
1798 vp.dwWidth = vp2.dwWidth = 640;
1799 vp.dwHeight = vp2.dwHeight = 480;
1800 vp.dvMinZ = vp2.dvMinZ = 0.0f;
1801 vp.dvMaxZ = vp2.dvMaxZ = 1.0f;
1802 vp.dvScaleX = vp.dwWidth / 2.0f;
1803 vp.dvScaleY = vp.dwHeight / 2.0f;
1804 vp.dvMaxX = 1.0f;
1805 vp.dvMaxY = 1.0f;
1806 vp2.dvClipX = -1.0f;
1807 vp2.dvClipY = 1.0f;
1808 vp2.dvClipWidth = 2.0f;
1809 vp2.dvClipHeight = 2.0f;
1810 hr = IDirect3DViewport2_SetViewport(viewport2, &vp);
1811 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1812 hr = IDirect3DViewport2_SetViewport2(viewport2, &vp2);
1813 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1815 vp.dwSize = sizeof(vp);
1816 hr = IDirect3DViewport2_SetViewport(viewport2, &vp);
1817 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#lx.\n", hr);
1818 vp2.dwSize = sizeof(vp2);
1819 hr = IDirect3DViewport2_SetViewport2(viewport2, &vp2);
1820 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#lx.\n", hr);
1822 /* Destroying the device removes the viewport, but does not free the reference
1823 * added by SetCurrentViewport. */
1824 IDirect3DDevice2_Release(device);
1825 ref = get_refcount((IUnknown *) viewport2);
1826 todo_wine ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1828 vp.dwSize = sizeof(vp);
1829 hr = IDirect3DViewport2_SetViewport(viewport2, &vp);
1830 ok(hr == D3DERR_VIEWPORTHASNODEVICE, "Got unexpected hr %#lx.\n", hr);
1831 vp2.dwSize = sizeof(vp2);
1832 hr = IDirect3DViewport2_SetViewport2(viewport2, &vp2);
1833 ok(hr == D3DERR_VIEWPORTHASNODEVICE, "Got unexpected hr %#lx.\n", hr);
1835 IDirect3DViewport2_Release(another_vp);
1836 IDirect3DViewport2_Release(viewport2);
1837 IDirect3D2_Release(d3d);
1838 DestroyWindow(window);
1839 IDirectDraw2_Release(ddraw);
1842 static void test_zenable(const GUID *device_guid)
1844 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1845 static D3DTLVERTEX tquad[] =
1847 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1848 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1849 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1850 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1852 IDirect3DMaterial2 *background;
1853 unsigned int color, x, y, i, j;
1854 IDirect3DViewport2 *viewport;
1855 IDirect3DDevice2 *device;
1856 IDirectDrawSurface *rt;
1857 IDirectDraw2 *ddraw;
1858 HWND window;
1859 HRESULT hr;
1861 window = create_window();
1862 ddraw = create_ddraw();
1863 ok(!!ddraw, "Failed to create a ddraw object.\n");
1864 if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid, NULL)))
1866 skip("Failed to create a 3D device, skipping test.\n");
1867 IDirectDraw2_Release(ddraw);
1868 DestroyWindow(window);
1869 return;
1872 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1873 viewport = create_viewport(device, 0, 0, 640, 480);
1874 viewport_set_background(device, viewport, background);
1875 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1876 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1878 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1879 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1881 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1882 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1884 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1885 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1887 color = get_surface_color(rt, 80, 60);
1888 /* For some reason clears and colour fill blits randomly fail with software render target. */
1889 ok(color == 0x00ff0000 || broken(is_software_device_type(device_guid) && !color),
1890 "Got unexpected colour 0x%08x.\n", color);
1891 if (!color)
1893 fill_surface(rt, 0xffff0000);
1895 color = get_surface_color(rt, 80, 60);
1896 ok(color == 0x00ff0000, "Got unexpected colour 0x%08x.\n", color);
1899 hr = IDirect3DDevice2_BeginScene(device);
1900 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1901 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, tquad, 4, 0);
1902 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1903 hr = IDirect3DDevice2_EndScene(device);
1904 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1906 for (i = 0; i < 4; ++i)
1908 for (j = 0; j < 4; ++j)
1910 x = 80 * ((2 * j) + 1);
1911 y = 60 * ((2 * i) + 1);
1912 color = get_surface_color(rt, x, y);
1913 ok(compare_color(color, 0x0000ff00, 1),
1914 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1917 IDirectDrawSurface_Release(rt);
1919 destroy_viewport(device, viewport);
1920 destroy_material(background);
1921 IDirect3DDevice2_Release(device);
1922 IDirectDraw2_Release(ddraw);
1923 DestroyWindow(window);
1926 static void test_ck_rgba(const GUID *device_guid)
1928 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1929 static D3DTLVERTEX tquad[] =
1931 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1932 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1933 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1934 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1935 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1936 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1937 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1938 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1940 static const struct
1942 D3DCOLOR fill_color;
1943 BOOL color_key;
1944 BOOL blend;
1945 unsigned int result1, result1_broken;
1946 unsigned int result2, result2_broken;
1948 tests[] =
1950 /* r200 on Windows doesn't check the alpha component when applying the color
1951 * key, so the key matches on every texel. */
1952 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1953 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1954 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1955 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1956 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1957 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1958 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1959 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1962 D3DTEXTUREHANDLE texture_handle;
1963 IDirect3DMaterial2 *background;
1964 IDirectDrawSurface *surface;
1965 IDirect3DViewport2 *viewport;
1966 IDirect3DTexture2 *texture;
1967 DDSURFACEDESC surface_desc;
1968 IDirect3DDevice2 *device;
1969 IDirectDrawSurface *rt;
1970 unsigned int color, i;
1971 IDirectDraw2 *ddraw;
1972 HWND window;
1973 DDBLTFX fx;
1974 HRESULT hr;
1976 window = create_window();
1977 ddraw = create_ddraw();
1978 ok(!!ddraw, "Failed to create a ddraw object.\n");
1979 if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid, NULL)))
1981 skip("Failed to create a 3D device, skipping test.\n");
1982 IDirectDraw2_Release(ddraw);
1983 DestroyWindow(window);
1984 return;
1987 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1988 viewport = create_viewport(device, 0, 0, 640, 480);
1989 viewport_set_background(device, viewport, background);
1990 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1991 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
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 if (is_software_device_type(device_guid))
1998 surface_desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
1999 surface_desc.dwWidth = 256;
2000 surface_desc.dwHeight = 256;
2001 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
2002 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
2003 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
2004 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
2005 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
2006 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
2007 surface_desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
2008 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
2009 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
2010 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2011 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
2012 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
2013 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
2014 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
2015 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2016 IDirect3DTexture2_Release(texture);
2018 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
2019 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2020 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
2021 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2022 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
2023 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2025 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
2026 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2028 for (i = 0; i < ARRAY_SIZE(tests); ++i)
2030 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
2031 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2032 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
2033 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2035 memset(&fx, 0, sizeof(fx));
2036 fx.dwSize = sizeof(fx);
2037 fx.dwFillColor = tests[i].fill_color;
2038 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
2039 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
2041 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
2042 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2043 /* RT clears are broken on Windows for software render target. */
2044 if (is_software_device_type(device_guid))
2045 fill_surface(rt, 0xffff0000);
2047 hr = IDirect3DDevice2_BeginScene(device);
2048 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2049 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
2050 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2051 hr = IDirect3DDevice2_EndScene(device);
2052 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2054 color = get_surface_color(rt, 320, 240);
2055 ok(compare_color(color, tests[i].result1, 2) || compare_color(color, tests[i].result1_broken, 1),
2056 "Expected color 0x%08x for test %u, got 0x%08x.\n",
2057 tests[i].result1, i, color);
2059 fx.dwFillColor = 0xff0000ff;
2060 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
2061 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
2063 hr = IDirect3DDevice2_BeginScene(device);
2064 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2065 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[4], 4, 0);
2066 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2067 hr = IDirect3DDevice2_EndScene(device);
2068 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2070 /* This tests that fragments that are masked out by the color key are
2071 * discarded, instead of just fully transparent. */
2072 color = get_surface_color(rt, 320, 240);
2073 ok(compare_color(color, tests[i].result2, 2) || compare_color(color, tests[i].result2_broken, 1),
2074 "Expected color 0x%08x for test %u, got 0x%08x.\n",
2075 tests[i].result2, i, color);
2078 IDirectDrawSurface_Release(rt);
2079 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
2080 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2081 IDirectDrawSurface_Release(surface);
2082 destroy_viewport(device, viewport);
2083 destroy_material(background);
2084 IDirect3DDevice2_Release(device);
2085 IDirectDraw2_Release(ddraw);
2086 DestroyWindow(window);
2089 static void test_ck_default(void)
2091 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
2092 static D3DTLVERTEX tquad[] =
2094 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
2095 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
2096 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
2097 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
2099 IDirectDrawSurface *surface, *rt;
2100 D3DTEXTUREHANDLE texture_handle;
2101 IDirect3DMaterial2 *background;
2102 IDirect3DViewport2 *viewport;
2103 DDSURFACEDESC surface_desc;
2104 IDirect3DTexture2 *texture;
2105 IDirect3DDevice2 *device;
2106 IDirectDraw2 *ddraw;
2107 unsigned int color;
2108 DWORD value;
2109 HWND window;
2110 DDBLTFX fx;
2111 HRESULT hr;
2113 window = create_window();
2114 ddraw = create_ddraw();
2115 ok(!!ddraw, "Failed to create a ddraw object.\n");
2116 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2118 skip("Failed to create a 3D device, skipping test.\n");
2119 IDirectDraw2_Release(ddraw);
2120 DestroyWindow(window);
2121 return;
2124 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
2125 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
2127 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
2128 viewport = create_viewport(device, 0, 0, 640, 480);
2129 viewport_set_background(device, viewport, background);
2130 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
2131 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
2133 memset(&surface_desc, 0, sizeof(surface_desc));
2134 surface_desc.dwSize = sizeof(surface_desc);
2135 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
2136 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2137 surface_desc.dwWidth = 256;
2138 surface_desc.dwHeight = 256;
2139 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
2140 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
2141 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
2142 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
2143 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
2144 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
2145 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
2146 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
2147 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2148 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
2149 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
2150 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
2151 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
2152 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#lx.\n", hr);
2153 IDirect3DTexture_Release(texture);
2155 memset(&fx, 0, sizeof(fx));
2156 fx.dwSize = sizeof(fx);
2157 fx.dwFillColor = 0x000000ff;
2158 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
2159 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#lx.\n", hr);
2161 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2162 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
2163 hr = IDirect3DDevice2_BeginScene(device);
2164 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
2165 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
2166 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#lx.\n", hr);
2167 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
2168 ok(SUCCEEDED(hr), "Failed to get render state, hr %#lx.\n", hr);
2169 ok(!value, "Got unexpected color keying state %#lx.\n", value);
2170 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
2171 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
2172 hr = IDirect3DDevice2_EndScene(device);
2173 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
2174 color = get_surface_color(rt, 320, 240);
2175 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
2177 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2178 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
2179 hr = IDirect3DDevice2_BeginScene(device);
2180 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
2181 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
2182 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#lx.\n", hr);
2183 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
2184 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
2185 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
2186 ok(SUCCEEDED(hr), "Failed to get render state, hr %#lx.\n", hr);
2187 ok(!!value, "Got unexpected color keying state %#lx.\n", value);
2188 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
2189 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#lx.\n", hr);
2190 hr = IDirect3DDevice2_EndScene(device);
2191 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
2192 color = get_surface_color(rt, 320, 240);
2193 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
2195 IDirectDrawSurface_Release(surface);
2196 destroy_viewport(device, viewport);
2197 destroy_material(background);
2198 IDirectDrawSurface_Release(rt);
2199 IDirect3DDevice2_Release(device);
2200 IDirectDraw2_Release(ddraw);
2201 DestroyWindow(window);
2204 static void test_ck_complex(void)
2206 IDirectDrawSurface *surface, *mipmap, *tmp;
2207 DDSCAPS caps = {DDSCAPS_COMPLEX};
2208 DDSURFACEDESC surface_desc;
2209 IDirect3DDevice2 *device;
2210 DDCOLORKEY color_key;
2211 IDirectDraw2 *ddraw;
2212 unsigned int i;
2213 ULONG refcount;
2214 HWND window;
2215 HRESULT hr;
2217 window = create_window();
2218 ddraw = create_ddraw();
2219 ok(!!ddraw, "Failed to create a ddraw object.\n");
2220 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
2222 skip("Failed to create a 3D device, skipping test.\n");
2223 DestroyWindow(window);
2224 IDirectDraw2_Release(ddraw);
2225 return;
2227 IDirect3DDevice2_Release(device);
2229 memset(&surface_desc, 0, sizeof(surface_desc));
2230 surface_desc.dwSize = sizeof(surface_desc);
2231 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2232 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2233 surface_desc.dwWidth = 128;
2234 surface_desc.dwHeight = 128;
2235 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2236 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
2238 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2239 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx.\n", hr);
2240 color_key.dwColorSpaceLowValue = 0x0000ff00;
2241 color_key.dwColorSpaceHighValue = 0x0000ff00;
2242 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2243 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
2244 memset(&color_key, 0, sizeof(color_key));
2245 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2246 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
2247 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2248 color_key.dwColorSpaceLowValue);
2249 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2250 color_key.dwColorSpaceHighValue);
2252 mipmap = surface;
2253 IDirectDrawSurface_AddRef(mipmap);
2254 for (i = 0; i < 7; ++i)
2256 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
2257 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#lx.\n", i, hr);
2259 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2260 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx, i %u.\n", hr, i);
2261 color_key.dwColorSpaceLowValue = 0x000000ff;
2262 color_key.dwColorSpaceHighValue = 0x000000ff;
2263 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2264 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx, i %u.\n", hr, i);
2265 memset(&color_key, 0, sizeof(color_key));
2266 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2267 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx, i %u.\n", hr, i);
2268 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08lx, i %u.\n",
2269 color_key.dwColorSpaceLowValue, i);
2270 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08lx, i %u.\n",
2271 color_key.dwColorSpaceHighValue, i);
2273 IDirectDrawSurface_Release(mipmap);
2274 mipmap = tmp;
2277 memset(&color_key, 0, sizeof(color_key));
2278 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2279 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
2280 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2281 color_key.dwColorSpaceLowValue);
2282 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2283 color_key.dwColorSpaceHighValue);
2285 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
2286 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
2287 IDirectDrawSurface_Release(mipmap);
2288 refcount = IDirectDrawSurface_Release(surface);
2289 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
2291 memset(&surface_desc, 0, sizeof(surface_desc));
2292 surface_desc.dwSize = sizeof(surface_desc);
2293 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
2294 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
2295 surface_desc.dwBackBufferCount = 1;
2296 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2297 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
2299 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2300 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx.\n", hr);
2301 color_key.dwColorSpaceLowValue = 0x0000ff00;
2302 color_key.dwColorSpaceHighValue = 0x0000ff00;
2303 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2304 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
2305 memset(&color_key, 0, sizeof(color_key));
2306 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2307 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
2308 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2309 color_key.dwColorSpaceLowValue);
2310 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2311 color_key.dwColorSpaceHighValue);
2313 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
2314 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#lx.\n", hr);
2316 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2317 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx, i %u.\n", hr, i);
2318 color_key.dwColorSpaceLowValue = 0x0000ff00;
2319 color_key.dwColorSpaceHighValue = 0x0000ff00;
2320 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2321 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
2322 memset(&color_key, 0, sizeof(color_key));
2323 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2324 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
2325 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2326 color_key.dwColorSpaceLowValue);
2327 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2328 color_key.dwColorSpaceHighValue);
2330 IDirectDrawSurface_Release(tmp);
2332 refcount = IDirectDrawSurface_Release(surface);
2333 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
2334 refcount = IDirectDraw2_Release(ddraw);
2335 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
2336 DestroyWindow(window);
2339 struct qi_test
2341 REFIID iid;
2342 REFIID refcount_iid;
2343 HRESULT hr;
2346 static void test_qi(const char *test_name, IUnknown *base_iface,
2347 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
2349 ULONG refcount, expected_refcount;
2350 IUnknown *iface1, *iface2;
2351 HRESULT hr;
2352 UINT i, j;
2354 for (i = 0; i < entry_count; ++i)
2356 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
2357 ok(hr == tests[i].hr, "Got hr %#lx for test \"%s\" %u.\n", hr, test_name, i);
2358 if (SUCCEEDED(hr))
2360 for (j = 0; j < entry_count; ++j)
2362 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
2363 ok(hr == tests[j].hr, "Got hr %#lx for test \"%s\" %u, %u.\n", hr, test_name, i, j);
2364 if (SUCCEEDED(hr))
2366 expected_refcount = 0;
2367 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
2368 ++expected_refcount;
2369 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
2370 ++expected_refcount;
2371 refcount = IUnknown_Release(iface2);
2372 ok(refcount == expected_refcount, "Got refcount %lu for test \"%s\" %u, %u, expected %lu.\n",
2373 refcount, test_name, i, j, expected_refcount);
2377 expected_refcount = 0;
2378 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
2379 ++expected_refcount;
2380 refcount = IUnknown_Release(iface1);
2381 ok(refcount == expected_refcount, "Got refcount %lu for test \"%s\" %u, expected %lu.\n",
2382 refcount, test_name, i, expected_refcount);
2387 static void test_surface_qi(void)
2389 static const struct qi_test tests[] =
2391 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
2392 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
2393 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
2394 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2395 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
2396 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
2397 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
2398 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
2399 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
2400 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
2401 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
2402 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
2403 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
2404 {&IID_IDirect3D7, NULL, E_INVALIDARG },
2405 {&IID_IDirect3D3, NULL, E_INVALIDARG },
2406 {&IID_IDirect3D2, NULL, E_INVALIDARG },
2407 {&IID_IDirect3D, NULL, E_INVALIDARG },
2408 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
2409 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
2410 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
2411 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
2412 {&IID_IDirectDraw, NULL, E_INVALIDARG },
2413 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
2414 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
2415 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
2416 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
2417 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
2418 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
2419 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
2420 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
2421 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
2422 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
2423 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
2424 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
2425 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
2426 {NULL, NULL, E_INVALIDARG },
2429 IDirectDrawSurface *surface;
2430 DDSURFACEDESC surface_desc;
2431 IDirect3DDevice2 *device;
2432 IDirectDraw2 *ddraw;
2433 HWND window;
2434 HRESULT hr;
2436 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
2438 win_skip("DirectDrawCreateEx not available, skipping test.\n");
2439 return;
2442 window = create_window();
2443 ddraw = create_ddraw();
2444 ok(!!ddraw, "Failed to create a ddraw object.\n");
2445 /* Try to create a D3D device to see if the ddraw implementation supports
2446 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
2447 * doesn't support e.g. the IDirect3DTexture interfaces. */
2448 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2450 skip("Failed to create a 3D device, skipping test.\n");
2451 IDirectDraw2_Release(ddraw);
2452 DestroyWindow(window);
2453 return;
2455 IDirect3DDevice_Release(device);
2457 memset(&surface_desc, 0, sizeof(surface_desc));
2458 surface_desc.dwSize = sizeof(surface_desc);
2459 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2460 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2461 surface_desc.dwWidth = 512;
2462 surface_desc.dwHeight = 512;
2463 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, (IDirectDrawSurface **)0xdeadbeef, NULL);
2464 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
2465 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2466 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
2468 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, ARRAY_SIZE(tests));
2470 IDirectDrawSurface_Release(surface);
2471 IDirectDraw2_Release(ddraw);
2472 DestroyWindow(window);
2475 static void test_device_qi(void)
2477 static const struct qi_test tests[] =
2479 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2480 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2481 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2482 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2483 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2484 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2485 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2486 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2487 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2488 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
2489 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
2490 {&IID_IDirect3DDevice2, &IID_IDirect3DDevice2, S_OK },
2491 {&IID_IDirect3DDevice, &IID_IDirect3DDevice2, S_OK },
2492 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2493 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2494 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2495 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2496 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2497 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2498 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2499 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2500 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2501 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2502 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2503 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2504 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2505 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2506 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2507 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2508 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2509 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2510 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2511 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2512 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2513 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2514 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2515 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2516 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2517 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2518 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2519 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2520 {&IID_IUnknown, &IID_IDirect3DDevice2, S_OK },
2523 IDirect3DDevice2 *device;
2524 IDirectDraw2 *ddraw;
2525 HWND window;
2527 window = create_window();
2528 ddraw = create_ddraw();
2529 ok(!!ddraw, "Failed to create a ddraw object.\n");
2530 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2532 skip("Failed to create a 3D device, skipping test.\n");
2533 IDirectDraw2_Release(ddraw);
2534 DestroyWindow(window);
2535 return;
2538 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice2, tests, ARRAY_SIZE(tests));
2540 IDirect3DDevice2_Release(device);
2541 IDirectDraw2_Release(ddraw);
2542 DestroyWindow(window);
2545 static void test_wndproc(void)
2547 LONG_PTR proc, ddraw_proc;
2548 IDirectDraw2 *ddraw;
2549 WNDCLASSA wc = {0};
2550 HWND window;
2551 HRESULT hr;
2552 ULONG ref;
2554 static struct message messages[] =
2556 {WM_WINDOWPOSCHANGING, FALSE, 0},
2557 {WM_MOVE, FALSE, 0},
2558 {WM_SIZE, FALSE, 0},
2559 {WM_WINDOWPOSCHANGING, FALSE, 0},
2560 {WM_ACTIVATE, FALSE, 0},
2561 {WM_SETFOCUS, FALSE, 0},
2562 {0, FALSE, 0},
2565 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2566 ddraw = create_ddraw();
2567 ok(!!ddraw, "Failed to create a ddraw object.\n");
2569 wc.lpfnWndProc = test_proc;
2570 wc.lpszClassName = "ddraw_test_wndproc_wc";
2571 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2573 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2574 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2576 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2577 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2578 (LONG_PTR)test_proc, proc);
2579 expect_messages = messages;
2580 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2581 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2582 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2583 expect_messages = NULL;
2584 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2585 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix, got %#Ix.\n",
2586 (LONG_PTR)test_proc, proc);
2587 ref = IDirectDraw2_Release(ddraw);
2588 ok(!ref, "Unexpected refcount %lu.\n", ref);
2589 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2590 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2591 (LONG_PTR)test_proc, proc);
2593 /* DDSCL_NORMAL doesn't. */
2594 ddraw = create_ddraw();
2595 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2596 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2597 (LONG_PTR)test_proc, proc);
2598 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2599 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2600 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2601 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2602 (LONG_PTR)test_proc, proc);
2603 ref = IDirectDraw2_Release(ddraw);
2604 ok(!ref, "Unexpected refcount %lu.\n", ref);
2605 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2606 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2607 (LONG_PTR)test_proc, proc);
2609 /* The original window proc is only restored by ddraw if the current
2610 * window proc matches the one ddraw set. This also affects switching
2611 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2612 ddraw = create_ddraw();
2613 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2614 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2615 (LONG_PTR)test_proc, proc);
2616 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2617 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2618 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2619 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix, got %#Ix.\n",
2620 (LONG_PTR)test_proc, proc);
2621 ddraw_proc = proc;
2622 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2623 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2624 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2625 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2626 (LONG_PTR)test_proc, proc);
2627 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2628 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2629 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2630 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix, got %#Ix.\n",
2631 (LONG_PTR)test_proc, proc);
2632 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2633 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2634 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2635 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#Ix, got %#Ix.\n",
2636 (LONG_PTR)DefWindowProcA, proc);
2637 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2638 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2639 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, ddraw_proc);
2640 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#Ix, got %#Ix.\n",
2641 (LONG_PTR)DefWindowProcA, proc);
2642 ref = IDirectDraw2_Release(ddraw);
2643 ok(!ref, "Unexpected refcount %lu.\n", ref);
2644 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2645 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2646 (LONG_PTR)test_proc, proc);
2648 ddraw = create_ddraw();
2649 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2650 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2651 (LONG_PTR)test_proc, proc);
2652 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2653 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2654 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2655 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix, got %#Ix.\n",
2656 (LONG_PTR)test_proc, proc);
2657 ref = IDirectDraw2_Release(ddraw);
2658 ok(!ref, "Unexpected refcount %lu.\n", ref);
2659 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2660 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#Ix, got %#Ix.\n",
2661 (LONG_PTR)DefWindowProcA, proc);
2663 fix_wndproc(window, (LONG_PTR)test_proc);
2664 expect_messages = NULL;
2665 DestroyWindow(window);
2666 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2669 static void test_window_style(void)
2671 LONG style, exstyle, tmp, expected_style;
2672 RECT fullscreen_rect, r;
2673 HWND window, window2;
2674 IDirectDraw2 *ddraw;
2675 HRESULT hr;
2676 ULONG ref;
2677 BOOL ret;
2679 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2680 0, 0, 100, 100, 0, 0, 0, 0);
2681 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2682 0, 0, 50, 50, 0, 0, 0, 0);
2683 ddraw = create_ddraw();
2684 ok(!!ddraw, "Failed to create a ddraw object.\n");
2686 style = GetWindowLongA(window, GWL_STYLE);
2687 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2688 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2690 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2691 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2693 tmp = GetWindowLongA(window, GWL_STYLE);
2694 todo_wine ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2695 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2696 todo_wine ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2698 GetWindowRect(window, &r);
2699 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2700 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2701 GetClientRect(window, &r);
2702 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2704 ret = SetForegroundWindow(GetDesktopWindow());
2705 ok(ret, "Failed to set foreground window.\n");
2707 tmp = GetWindowLongA(window, GWL_STYLE);
2708 todo_wine ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2709 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2710 todo_wine ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2712 ret = SetForegroundWindow(window);
2713 ok(ret, "Failed to set foreground window.\n");
2714 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2715 * the next tests expect this. */
2716 ShowWindow(window, SW_HIDE);
2718 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2719 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2721 tmp = GetWindowLongA(window, GWL_STYLE);
2722 ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2723 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2724 ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2726 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_NOWINDOWCHANGES);
2727 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2729 tmp = GetWindowLongA(window, GWL_STYLE);
2730 todo_wine ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2731 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2732 todo_wine ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2734 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2735 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2737 tmp = GetWindowLongA(window, GWL_STYLE);
2738 expected_style = style | WS_VISIBLE;
2739 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
2740 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2741 expected_style = exstyle | WS_EX_TOPMOST;
2742 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2744 ShowWindow(window, SW_HIDE);
2745 tmp = GetWindowLongA(window, GWL_STYLE);
2746 todo_wine ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2747 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2748 expected_style = exstyle | WS_EX_TOPMOST;
2749 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2751 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_NOWINDOWCHANGES);
2752 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2754 tmp = GetWindowLongA(window, GWL_STYLE);
2755 ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2756 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2757 expected_style = exstyle | WS_EX_TOPMOST;
2758 ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2760 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2761 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2763 tmp = GetWindowLongA(window, GWL_STYLE);
2764 ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2765 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2766 expected_style = exstyle | WS_EX_TOPMOST;
2767 ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2769 ret = SetForegroundWindow(window);
2770 ok(ret, "Failed to set foreground window.\n");
2772 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2773 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2775 tmp = GetWindowLongA(window, GWL_STYLE);
2776 expected_style = style | WS_VISIBLE;
2777 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
2778 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2779 expected_style = exstyle | WS_EX_TOPMOST;
2780 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2782 ShowWindow(window, SW_HIDE);
2783 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2784 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2786 tmp = GetWindowLongA(window, GWL_STYLE);
2787 ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2788 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2789 ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2791 ShowWindow(window, SW_SHOW);
2792 ret = SetForegroundWindow(GetDesktopWindow());
2793 ok(ret, "Failed to set foreground window.\n");
2794 SetActiveWindow(window);
2795 ok(GetActiveWindow() == window, "Unexpected active window.\n");
2796 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2797 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2799 tmp = GetWindowLongA(window, GWL_STYLE);
2800 expected_style = style | WS_VISIBLE;
2801 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
2802 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2803 todo_wine ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2805 GetWindowRect(window, &r);
2806 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2807 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2809 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2810 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2812 SetWindowPos(window, NULL, 0, 0, 100, 100, SWP_NOZORDER | SWP_NOACTIVATE);
2813 GetWindowRect(window, &r);
2814 ok(!EqualRect(&r, &fullscreen_rect), "Window resize failed? got %s.\n",
2815 wine_dbgstr_rect(&r));
2817 ret = SetForegroundWindow(window2);
2818 ok(ret, "Failed to set foreground window.\n");
2819 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2820 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2822 tmp = GetWindowLongA(window, GWL_STYLE);
2823 expected_style = style | WS_VISIBLE;
2824 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
2825 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2826 todo_wine ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2828 GetWindowRect(window, &r);
2829 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2830 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2832 ret = SetForegroundWindow(window);
2833 ok(ret, "Failed to set foreground window.\n");
2834 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2835 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2837 tmp = GetWindowLongA(window, GWL_STYLE);
2838 expected_style = style | WS_VISIBLE;
2839 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
2840 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2841 expected_style = exstyle | WS_EX_TOPMOST;
2842 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2844 ShowWindow(window, SW_HIDE);
2845 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2846 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2848 tmp = GetWindowLongA(window, GWL_STYLE);
2849 ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2850 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2851 ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2853 ShowWindow(window, SW_SHOW);
2854 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2855 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2857 tmp = GetWindowLongA(window, GWL_STYLE);
2858 expected_style = style | WS_VISIBLE;
2859 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
2860 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2861 expected_style = exstyle | WS_EX_TOPMOST;
2862 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2864 ret = SetForegroundWindow(GetDesktopWindow());
2865 ok(ret, "Failed to set foreground window.\n");
2866 tmp = GetWindowLongA(window, GWL_STYLE);
2867 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2868 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
2869 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2870 expected_style = exstyle | WS_EX_TOPMOST;
2871 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2873 /* Test that there is a ~1.5s timer that checks and restores WS_EX_TOPMOST if it's missing */
2874 ret = ShowWindow(window, SW_RESTORE);
2875 ok(ret, "ShowWindow failed, error %#lx.\n", GetLastError());
2876 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2877 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2878 flush_events();
2880 /* Remove WS_VISIBLE and WS_EX_TOPMOST */
2881 tmp = GetWindowLongA(window, GWL_STYLE);
2882 ok(tmp & WS_VISIBLE, "Expected WS_VISIBLE.\n");
2883 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2884 ok(tmp & WS_EX_TOPMOST, "Expected WS_EX_TOPMOST.\n");
2885 ret = ShowWindow(window, SW_HIDE);
2886 ok(ret, "ShowWindow failed, error %#lx.\n", GetLastError());
2887 ret = SetWindowPos(window, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
2888 ok(ret, "SetWindowPos failed, error %#lx.\n", GetLastError());
2889 tmp = GetWindowLongA(window, GWL_STYLE);
2890 ok(!(tmp & WS_VISIBLE), "Got unexpected WS_VISIBLE.\n");
2891 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2892 ok(!(tmp & WS_EX_TOPMOST), "Got unexpected WS_EX_TOPMOST.\n");
2894 Sleep(2000);
2895 flush_events();
2897 /* WS_VISIBLE is not restored but WS_EX_TOPMOST is */
2898 tmp = GetWindowLongA(window, GWL_STYLE);
2899 ok(!(tmp & WS_VISIBLE), "Got unexpected WS_VISIBLE.\n");
2900 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2901 ok(tmp & WS_EX_TOPMOST, "Expected WS_EX_TOPMOST.\n");
2903 ref = IDirectDraw2_Release(ddraw);
2904 ok(!ref, "Unexpected refcount %lu.\n", ref);
2906 DestroyWindow(window2);
2907 DestroyWindow(window);
2910 static void test_redundant_mode_set(void)
2912 DDSURFACEDESC surface_desc = {0};
2913 IDirectDraw2 *ddraw;
2914 RECT q, r, s;
2915 HWND window;
2916 HRESULT hr;
2917 ULONG ref;
2919 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2920 0, 0, 100, 100, 0, 0, 0, 0);
2921 ddraw = create_ddraw();
2922 ok(!!ddraw, "Failed to create a ddraw object.\n");
2924 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2925 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2927 surface_desc.dwSize = sizeof(surface_desc);
2928 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
2929 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#lx.\n", hr);
2931 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2932 surface_desc.ddpfPixelFormat.dwRGBBitCount, 0, 0);
2933 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#lx.\n", hr);
2935 GetWindowRect(window, &q);
2936 r = q;
2937 r.right /= 2;
2938 r.bottom /= 2;
2939 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2940 GetWindowRect(window, &s);
2941 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2943 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2944 surface_desc.ddpfPixelFormat.dwRGBBitCount, 0, 0);
2945 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#lx.\n", hr);
2947 GetWindowRect(window, &s);
2948 ok(EqualRect(&r, &s) || broken(EqualRect(&q, &s) /* Windows 10 */),
2949 "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2951 ref = IDirectDraw2_Release(ddraw);
2952 ok(!ref, "Unexpected refcount %lu.\n", ref);
2954 DestroyWindow(window);
2957 static SIZE screen_size, screen_size2;
2959 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2961 if (message == WM_SIZE)
2963 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2964 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2967 return test_proc(hwnd, message, wparam, lparam);
2970 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2972 if (message == WM_SIZE)
2974 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2975 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2978 return test_proc(hwnd, message, wparam, lparam);
2981 struct test_coop_level_mode_set_enum_param
2983 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2986 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC *surface_desc, void *context)
2988 struct test_coop_level_mode_set_enum_param *param = context;
2990 if (surface_desc->ddpfPixelFormat.dwRGBBitCount != registry_mode.dmBitsPerPel)
2991 return DDENUMRET_OK;
2992 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2993 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2994 return DDENUMRET_OK;
2996 if (!param->ddraw_width)
2998 param->ddraw_width = surface_desc->dwWidth;
2999 param->ddraw_height = surface_desc->dwHeight;
3000 return DDENUMRET_OK;
3002 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
3003 return DDENUMRET_OK;
3005 /* The docs say the DDENUMRET_CANCEL below cancels the enumeration, so the check should be
3006 * redundant. However, since Windows 10 this no longer works and the enumeration continues
3007 * until all supported modes are enumerated. Win8 and earlier do cancel.
3009 * Unrelatedly, some testbot machines report high res modes like 1920x1080, but suffer from
3010 * some problems when we actually try to set them (w10pro64 and its localization siblings).
3011 * Try to stay below the registry mode if possible. */
3012 if (!param->user32_width || (surface_desc->dwWidth < registry_mode.dmPelsWidth
3013 && surface_desc->dwHeight < registry_mode.dmPelsHeight))
3015 param->user32_width = surface_desc->dwWidth;
3016 param->user32_height = surface_desc->dwHeight;
3018 return DDENUMRET_CANCEL;
3021 static void test_coop_level_mode_set(void)
3023 DEVMODEW *original_modes = NULL, devmode, devmode2;
3024 unsigned int display_count = 0;
3025 IDirectDrawSurface *primary;
3026 RECT registry_rect, ddraw_rect, user32_rect, r;
3027 IDirectDraw2 *ddraw;
3028 DDSURFACEDESC ddsd;
3029 WNDCLASSA wc = {0};
3030 HWND window, window2;
3031 HRESULT hr;
3032 ULONG ref;
3033 MSG msg;
3034 struct test_coop_level_mode_set_enum_param param;
3035 BOOL ret;
3036 LONG change_ret;
3038 static const struct message exclusive_messages[] =
3040 {WM_WINDOWPOSCHANGING, FALSE, 0},
3041 {WM_WINDOWPOSCHANGED, FALSE, 0},
3042 {WM_SIZE, FALSE, 0},
3043 {WM_DISPLAYCHANGE, FALSE, 0},
3044 {0, FALSE, 0},
3046 static const struct message exclusive_focus_loss_messages[] =
3048 {WM_ACTIVATE, TRUE, WA_INACTIVE},
3049 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window resize due to mode change. */
3050 {WM_WINDOWPOSCHANGED, FALSE, 0},
3051 {WM_SIZE, TRUE, SIZE_RESTORED}, /* Generated by DefWindowProc. */
3052 {WM_DISPLAYCHANGE, FALSE, 0},
3053 {WM_KILLFOCUS, FALSE, 0},
3054 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window minimized. */
3055 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
3056 * SW_MINIMIZED, causing a recursive window activation that does not
3057 * produce the same result in Wine yet. Ignore the difference for now.
3058 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
3059 {WM_WINDOWPOSCHANGED, FALSE, 0},
3060 {WM_MOVE, FALSE, 0},
3061 {WM_SIZE, TRUE, SIZE_MINIMIZED},
3062 {WM_ACTIVATEAPP, TRUE, FALSE},
3063 {0, FALSE, 0},
3065 static const struct message exclusive_focus_restore_messages[] =
3067 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
3068 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
3069 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
3070 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
3071 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
3072 /* Native redundantly sets the window size here. */
3073 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
3074 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
3075 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
3076 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
3077 {0, FALSE, 0},
3079 static const struct message sc_restore_messages[] =
3081 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
3082 {WM_WINDOWPOSCHANGING, FALSE, 0},
3083 {WM_WINDOWPOSCHANGED, FALSE, 0},
3084 {WM_SIZE, TRUE, SIZE_RESTORED},
3085 {0, FALSE, 0},
3087 static const struct message sc_minimize_messages[] =
3089 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
3090 {WM_WINDOWPOSCHANGING, FALSE, 0},
3091 {WM_WINDOWPOSCHANGED, FALSE, 0},
3092 {WM_SIZE, TRUE, SIZE_MINIMIZED},
3093 {0, FALSE, 0},
3095 static const struct message sc_maximize_messages[] =
3097 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
3098 {WM_WINDOWPOSCHANGING, FALSE, 0},
3099 {WM_WINDOWPOSCHANGED, FALSE, 0},
3100 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
3101 {0, FALSE, 0},
3104 static const struct message normal_messages[] =
3106 {WM_DISPLAYCHANGE, FALSE, 0},
3107 {0, FALSE, 0},
3110 memset(&devmode, 0, sizeof(devmode));
3111 devmode.dmSize = sizeof(devmode);
3112 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3113 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3114 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3115 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
3116 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3117 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3119 ret = save_display_modes(&original_modes, &display_count);
3120 ok(ret, "Failed to save original display modes.\n");
3122 ddraw = create_ddraw();
3123 ok(!!ddraw, "Failed to create a ddraw object.\n");
3125 memset(&param, 0, sizeof(param));
3126 hr = IDirectDraw2_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
3127 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#lx.\n", hr);
3128 ref = IDirectDraw2_Release(ddraw);
3129 ok(!ref, "Unexpected refcount %lu.\n", ref);
3131 if (!param.user32_height)
3133 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
3134 free(original_modes);
3135 return;
3138 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3139 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
3140 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
3142 memset(&devmode, 0, sizeof(devmode));
3143 devmode.dmSize = sizeof(devmode);
3144 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3145 devmode.dmPelsWidth = param.user32_width;
3146 devmode.dmPelsHeight = param.user32_height;
3147 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3148 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3150 ddraw = create_ddraw();
3151 ok(!!ddraw, "Failed to create a ddraw object.\n");
3153 wc.lpfnWndProc = mode_set_proc;
3154 wc.lpszClassName = "ddraw_test_wndproc_wc";
3155 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3156 wc.lpfnWndProc = mode_set_proc2;
3157 wc.lpszClassName = "ddraw_test_wndproc_wc2";
3158 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3160 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
3161 0, 0, 100, 100, 0, 0, 0, 0);
3162 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
3163 0, 0, 100, 100, 0, 0, 0, 0);
3165 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3166 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3168 GetWindowRect(window, &r);
3169 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
3170 wine_dbgstr_rect(&r));
3172 memset(&ddsd, 0, sizeof(ddsd));
3173 ddsd.dwSize = sizeof(ddsd);
3174 ddsd.dwFlags = DDSD_CAPS;
3175 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3177 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3178 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3179 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3180 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3181 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %lu, got %lu.\n",
3182 param.user32_width, ddsd.dwWidth);
3183 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %lu, got %lu.\n",
3184 param.user32_height, ddsd.dwHeight);
3186 GetWindowRect(window, &r);
3187 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
3188 wine_dbgstr_rect(&r));
3190 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3191 expect_messages = exclusive_messages;
3192 screen_size.cx = 0;
3193 screen_size.cy = 0;
3195 hr = IDirectDrawSurface_IsLost(primary);
3196 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3197 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3198 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3199 hr = IDirectDrawSurface_IsLost(primary);
3200 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3202 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3203 expect_messages = NULL;
3204 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
3205 "Expected screen size %lux%lu, got %lux%lu.\n",
3206 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
3208 GetWindowRect(window, &r);
3209 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3210 wine_dbgstr_rect(&r));
3212 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3213 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3214 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %lu, got %lu.\n",
3215 param.user32_width, ddsd.dwWidth);
3216 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %lu, got %lu.\n",
3217 param.user32_height, ddsd.dwHeight);
3218 IDirectDrawSurface_Release(primary);
3220 memset(&ddsd, 0, sizeof(ddsd));
3221 ddsd.dwSize = sizeof(ddsd);
3222 ddsd.dwFlags = DDSD_CAPS;
3223 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3225 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3226 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3227 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3228 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3229 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3230 param.ddraw_width, ddsd.dwWidth);
3231 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3232 param.ddraw_height, ddsd.dwHeight);
3234 GetWindowRect(window, &r);
3235 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3236 wine_dbgstr_rect(&r));
3238 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3239 expect_messages = exclusive_messages;
3240 screen_size.cx = 0;
3241 screen_size.cy = 0;
3243 hr = IDirectDrawSurface_IsLost(primary);
3244 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3245 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3246 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3247 hr = IDirectDrawSurface_IsLost(primary);
3248 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3250 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3251 expect_messages = NULL;
3252 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
3253 "Expected screen size %lux%lu, got %lux%lu.\n",
3254 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
3256 GetWindowRect(window, &r);
3257 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
3258 wine_dbgstr_rect(&r));
3260 expect_messages = exclusive_focus_loss_messages;
3261 ret = SetForegroundWindow(GetDesktopWindow());
3262 ok(ret, "Failed to set foreground window.\n");
3263 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3264 memset(&devmode, 0, sizeof(devmode));
3265 devmode.dmSize = sizeof(devmode);
3266 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3267 ok(ret, "Failed to get display mode.\n");
3268 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3269 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpected screen size %lux%lu.\n",
3270 devmode.dmPelsWidth, devmode.dmPelsHeight);
3272 expect_messages = exclusive_focus_restore_messages;
3273 ShowWindow(window, SW_RESTORE);
3274 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3276 GetWindowRect(window, &r);
3277 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3278 wine_dbgstr_rect(&r));
3279 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3280 ok(ret, "Failed to get display mode.\n");
3281 ok(devmode.dmPelsWidth == param.ddraw_width
3282 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpected screen size %lux%lu.\n",
3283 devmode.dmPelsWidth, devmode.dmPelsHeight);
3285 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3286 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3287 /* Normally the primary should be restored here. Unfortunately this causes the
3288 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
3289 * testbot. Another Restore call would presumably avoid the crash, but it also moots
3290 * the point of the GetSurfaceDesc call. */
3292 expect_messages = sc_minimize_messages;
3293 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3294 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3295 expect_messages = NULL;
3297 expect_messages = sc_restore_messages;
3298 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
3299 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3300 expect_messages = NULL;
3302 expect_messages = sc_maximize_messages;
3303 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3304 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3305 expect_messages = NULL;
3307 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3308 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3310 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3311 expect_messages = exclusive_messages;
3312 screen_size.cx = 0;
3313 screen_size.cy = 0;
3315 hr = IDirectDrawSurface_IsLost(primary);
3316 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3317 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3318 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#lx.\n", hr);
3319 hr = IDirectDrawSurface_IsLost(primary);
3320 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3322 flaky /* win8 */
3323 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3324 expect_messages = NULL;
3325 flaky /* win8 */
3326 ok(screen_size.cx == registry_mode.dmPelsWidth
3327 && screen_size.cy == registry_mode.dmPelsHeight,
3328 "Expected screen size %lux%lu, got %lux%lu.\n",
3329 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
3331 GetWindowRect(window, &r);
3332 flaky /* win8 */
3333 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3334 wine_dbgstr_rect(&r));
3336 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3337 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3338 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3339 param.ddraw_width, ddsd.dwWidth);
3340 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3341 param.ddraw_height, ddsd.dwHeight);
3342 IDirectDrawSurface_Release(primary);
3344 /* For Wine. */
3345 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3346 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3347 flush_events();
3349 if (IsIconic(window)) /* make sure the window is restored, working around some Wine/X11 race condition */
3351 ShowWindow(window, SW_RESTORE);
3352 flush_events();
3355 memset(&ddsd, 0, sizeof(ddsd));
3356 ddsd.dwSize = sizeof(ddsd);
3357 ddsd.dwFlags = DDSD_CAPS;
3358 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3360 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3361 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3362 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3363 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3364 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3365 registry_mode.dmPelsWidth, ddsd.dwWidth);
3366 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3367 registry_mode.dmPelsHeight, ddsd.dwHeight);
3369 GetWindowRect(window, &r);
3370 flaky /* win8 */
3371 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3372 wine_dbgstr_rect(&r));
3374 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3375 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3377 GetWindowRect(window, &r);
3378 flaky /* win8 */
3379 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3380 wine_dbgstr_rect(&r));
3382 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3383 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3384 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3385 registry_mode.dmPelsWidth, ddsd.dwWidth);
3386 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3387 registry_mode.dmPelsHeight, ddsd.dwHeight);
3388 IDirectDrawSurface_Release(primary);
3390 memset(&ddsd, 0, sizeof(ddsd));
3391 ddsd.dwSize = sizeof(ddsd);
3392 ddsd.dwFlags = DDSD_CAPS;
3393 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3395 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3396 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3397 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3398 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3399 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3400 registry_mode.dmPelsWidth, ddsd.dwWidth);
3401 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3402 registry_mode.dmPelsHeight, ddsd.dwHeight);
3404 GetWindowRect(window, &r);
3405 flaky /* win8 */
3406 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3407 wine_dbgstr_rect(&r));
3409 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3410 expect_messages = normal_messages;
3411 screen_size.cx = 0;
3412 screen_size.cy = 0;
3414 hr = IDirectDrawSurface_IsLost(primary);
3415 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3416 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3417 devmode.dmPelsWidth = param.user32_width;
3418 devmode.dmPelsHeight = param.user32_height;
3419 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3420 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3421 hr = IDirectDrawSurface_IsLost(primary);
3422 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3424 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3425 expect_messages = NULL;
3426 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3428 GetWindowRect(window, &r);
3429 flaky /* win8 */
3430 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3431 wine_dbgstr_rect(&r));
3433 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3434 expect_messages = normal_messages;
3435 screen_size.cx = 0;
3436 screen_size.cy = 0;
3438 hr = IDirectDrawSurface_Restore(primary);
3439 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
3440 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3441 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
3443 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
3444 IDirectDrawSurface_Release(primary);
3445 IDirectDraw2_Release(ddraw);
3446 goto done;
3448 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3449 hr = IDirectDrawSurface_Restore(primary);
3450 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
3451 hr = IDirectDrawSurface_IsLost(primary);
3452 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3454 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3455 expect_messages = NULL;
3456 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3458 GetWindowRect(window, &r);
3459 flaky /* win8 */
3460 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3461 wine_dbgstr_rect(&r));
3463 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3464 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3465 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3466 registry_mode.dmPelsWidth, ddsd.dwWidth);
3467 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3468 registry_mode.dmPelsHeight, ddsd.dwHeight);
3469 IDirectDrawSurface_Release(primary);
3471 memset(&ddsd, 0, sizeof(ddsd));
3472 ddsd.dwSize = sizeof(ddsd);
3473 ddsd.dwFlags = DDSD_CAPS;
3474 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3476 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3477 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3478 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3479 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3480 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3481 param.ddraw_width, ddsd.dwWidth);
3482 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3483 param.ddraw_height, ddsd.dwHeight);
3485 GetWindowRect(window, &r);
3486 flaky /* win8 */
3487 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3488 wine_dbgstr_rect(&r));
3490 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3491 expect_messages = normal_messages;
3492 screen_size.cx = 0;
3493 screen_size.cy = 0;
3495 hr = IDirectDrawSurface_IsLost(primary);
3496 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3497 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3498 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#lx.\n", hr);
3499 hr = IDirectDrawSurface_IsLost(primary);
3500 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3502 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3503 expect_messages = NULL;
3504 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3506 GetWindowRect(window, &r);
3507 flaky /* win8 */
3508 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3509 wine_dbgstr_rect(&r));
3511 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3512 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3513 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3514 param.ddraw_width, ddsd.dwWidth);
3515 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3516 param.ddraw_height, ddsd.dwHeight);
3517 IDirectDrawSurface_Release(primary);
3519 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3520 ok(ret, "Failed to get display mode.\n");
3521 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3522 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3523 "Expected resolution %lux%lu, got %lux%lu.\n",
3524 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3525 devmode.dmPelsWidth, devmode.dmPelsHeight);
3526 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3527 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3529 memset(&ddsd, 0, sizeof(ddsd));
3530 ddsd.dwSize = sizeof(ddsd);
3531 ddsd.dwFlags = DDSD_CAPS;
3532 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3534 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3535 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3536 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3537 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3538 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3539 registry_mode.dmPelsWidth, ddsd.dwWidth);
3540 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3541 registry_mode.dmPelsHeight, ddsd.dwHeight);
3543 GetWindowRect(window, &r);
3544 flaky /* win8 */
3545 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3546 wine_dbgstr_rect(&r));
3548 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
3549 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
3550 * not DDSCL_FULLSCREEN. */
3551 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3552 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3554 GetWindowRect(window, &r);
3555 flaky /* win8 */
3556 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3557 wine_dbgstr_rect(&r));
3559 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3560 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3561 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3562 registry_mode.dmPelsWidth, ddsd.dwWidth);
3563 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3564 registry_mode.dmPelsHeight, ddsd.dwHeight);
3565 IDirectDrawSurface_Release(primary);
3567 memset(&ddsd, 0, sizeof(ddsd));
3568 ddsd.dwSize = sizeof(ddsd);
3569 ddsd.dwFlags = DDSD_CAPS;
3570 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3572 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3573 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3574 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3575 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3576 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3577 registry_mode.dmPelsWidth, ddsd.dwWidth);
3578 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3579 registry_mode.dmPelsHeight, ddsd.dwHeight);
3581 GetWindowRect(window, &r);
3582 flaky /* win8 */
3583 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3584 wine_dbgstr_rect(&r));
3586 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3587 expect_messages = normal_messages;
3588 screen_size.cx = 0;
3589 screen_size.cy = 0;
3591 hr = IDirectDrawSurface_IsLost(primary);
3592 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3593 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3594 devmode.dmPelsWidth = param.user32_width;
3595 devmode.dmPelsHeight = param.user32_height;
3596 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3597 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3598 hr = IDirectDrawSurface_IsLost(primary);
3599 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3601 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3602 expect_messages = NULL;
3603 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3605 GetWindowRect(window, &r);
3606 flaky /* win8 */
3607 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3608 wine_dbgstr_rect(&r));
3610 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3611 expect_messages = normal_messages;
3612 screen_size.cx = 0;
3613 screen_size.cy = 0;
3615 hr = IDirectDrawSurface_Restore(primary);
3616 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
3617 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3618 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3619 hr = IDirectDrawSurface_Restore(primary);
3620 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
3621 hr = IDirectDrawSurface_IsLost(primary);
3622 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3624 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3625 expect_messages = NULL;
3626 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3628 GetWindowRect(window, &r);
3629 flaky /* win8 */
3630 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3631 wine_dbgstr_rect(&r));
3633 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3634 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3635 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3636 registry_mode.dmPelsWidth, ddsd.dwWidth);
3637 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3638 registry_mode.dmPelsHeight, ddsd.dwHeight);
3639 IDirectDrawSurface_Release(primary);
3641 memset(&ddsd, 0, sizeof(ddsd));
3642 ddsd.dwSize = sizeof(ddsd);
3643 ddsd.dwFlags = DDSD_CAPS;
3644 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3646 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3647 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3648 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3649 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3650 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3651 param.ddraw_width, ddsd.dwWidth);
3652 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3653 param.ddraw_height, ddsd.dwHeight);
3655 GetWindowRect(window, &r);
3656 flaky /* win8 */
3657 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3658 wine_dbgstr_rect(&r));
3660 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3661 expect_messages = normal_messages;
3662 screen_size.cx = 0;
3663 screen_size.cy = 0;
3665 hr = IDirectDrawSurface_IsLost(primary);
3666 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3667 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3668 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#lx.\n", hr);
3669 hr = IDirectDrawSurface_IsLost(primary);
3670 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3672 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3673 expect_messages = NULL;
3674 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3676 GetWindowRect(window, &r);
3677 flaky /* win8 */
3678 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3679 wine_dbgstr_rect(&r));
3681 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3682 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3683 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3684 param.ddraw_width, ddsd.dwWidth);
3685 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3686 param.ddraw_height, ddsd.dwHeight);
3687 IDirectDrawSurface_Release(primary);
3689 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3690 ok(ret, "Failed to get display mode.\n");
3691 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3692 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3693 "Expected resolution %lux%lu, got %lux%lu.\n",
3694 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3695 devmode.dmPelsWidth, devmode.dmPelsHeight);
3696 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3697 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3699 memset(&ddsd, 0, sizeof(ddsd));
3700 ddsd.dwSize = sizeof(ddsd);
3701 ddsd.dwFlags = DDSD_CAPS;
3702 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3704 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3705 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3706 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3707 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3708 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3709 registry_mode.dmPelsWidth, ddsd.dwWidth);
3710 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3711 registry_mode.dmPelsHeight, ddsd.dwHeight);
3712 IDirectDrawSurface_Release(primary);
3714 GetWindowRect(window, &r);
3715 flaky /* win8 */
3716 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3717 wine_dbgstr_rect(&r));
3719 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3720 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3721 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3722 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3723 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3725 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3726 expect_messages = exclusive_messages;
3727 screen_size.cx = 0;
3728 screen_size.cy = 0;
3730 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3731 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3733 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3734 expect_messages = NULL;
3735 ok(screen_size.cx == registry_mode.dmPelsWidth
3736 && screen_size.cy == registry_mode.dmPelsHeight,
3737 "Expected screen size %lux%lu, got %lux%lu.\n",
3738 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3739 screen_size.cx, screen_size.cy);
3741 GetWindowRect(window, &r);
3742 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3743 wine_dbgstr_rect(&r));
3745 memset(&ddsd, 0, sizeof(ddsd));
3746 ddsd.dwSize = sizeof(ddsd);
3747 ddsd.dwFlags = DDSD_CAPS;
3748 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3750 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3751 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3752 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3753 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3754 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3755 registry_mode.dmPelsWidth, ddsd.dwWidth);
3756 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3757 registry_mode.dmPelsHeight, ddsd.dwHeight);
3758 IDirectDrawSurface_Release(primary);
3760 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3761 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3762 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3763 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3764 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3766 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3767 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3769 memset(&ddsd, 0, sizeof(ddsd));
3770 ddsd.dwSize = sizeof(ddsd);
3771 ddsd.dwFlags = DDSD_CAPS;
3772 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3774 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3775 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3776 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3777 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3778 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3779 param.ddraw_width, ddsd.dwWidth);
3780 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3781 param.ddraw_height, ddsd.dwHeight);
3782 IDirectDrawSurface_Release(primary);
3784 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3785 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#lx.\n", hr);
3787 flush_events(); /* flush any pending window resize X11 event */
3789 /* If the window is changed at the same time, messages are sent to the new window. */
3790 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3791 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3792 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3793 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3795 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3796 expect_messages = exclusive_messages;
3797 screen_size.cx = 0;
3798 screen_size.cy = 0;
3799 screen_size2.cx = 0;
3800 screen_size2.cy = 0;
3802 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3803 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3805 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3806 expect_messages = NULL;
3807 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n",
3808 screen_size.cx, screen_size.cy);
3809 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3810 "Expected screen size 2 %lux%lu, got %lux%lu.\n",
3811 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3813 GetWindowRect(window, &r);
3814 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3815 wine_dbgstr_rect(&r));
3816 GetWindowRect(window2, &r);
3817 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3818 wine_dbgstr_rect(&r));
3820 memset(&ddsd, 0, sizeof(ddsd));
3821 ddsd.dwSize = sizeof(ddsd);
3822 ddsd.dwFlags = DDSD_CAPS;
3823 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3825 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3826 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3827 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3828 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3829 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3830 registry_mode.dmPelsWidth, ddsd.dwWidth);
3831 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3832 registry_mode.dmPelsHeight, ddsd.dwHeight);
3833 IDirectDrawSurface_Release(primary);
3835 ref = IDirectDraw2_Release(ddraw);
3836 ok(!ref, "Unexpected refcount %lu.\n", ref);
3838 GetWindowRect(window, &r);
3839 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3840 wine_dbgstr_rect(&r));
3842 ret = restore_display_modes(original_modes, display_count);
3843 ok(ret, "Failed to restore display modes.\n");
3845 /* Test that no mode restorations if no mode changes happened */
3846 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3847 devmode.dmPelsWidth = param.user32_width;
3848 devmode.dmPelsHeight = param.user32_height;
3849 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3850 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %ld.\n", change_ret);
3852 ddraw = create_ddraw();
3853 ok(!!ddraw, "Failed to create a ddraw object.\n");
3854 ref = IDirectDraw2_Release(ddraw);
3855 ok(!ref, "Unexpected refcount %lu.\n", ref);
3857 memset(&devmode2, 0, sizeof(devmode2));
3858 devmode2.dmSize = sizeof(devmode2);
3859 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3860 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3861 ok(compare_mode_rect(&devmode2, &registry_mode), "Got a different mode.\n");
3862 ret = restore_display_modes(original_modes, display_count);
3863 ok(ret, "Failed to restore display modes.\n");
3865 /* Test that no mode restorations if no mode changes happened with fullscreen ddraw objects */
3866 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3867 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %ld.\n", change_ret);
3869 ddraw = create_ddraw();
3870 ok(!!ddraw, "Failed to create a ddraw object.\n");
3871 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3872 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
3873 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3874 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
3875 ref = IDirectDraw2_Release(ddraw);
3876 ok(!ref, "Unexpected refcount %lu.\n", ref);
3878 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3879 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3880 ok(compare_mode_rect(&devmode2, &registry_mode), "Got a different mode.\n");
3881 ret = restore_display_modes(original_modes, display_count);
3882 ok(ret, "Failed to restore display modes.\n");
3884 /* Test that mode restorations use display settings in the registry after ddraw object releases
3885 * if SetDisplayMode() was called */
3886 ddraw = create_ddraw();
3887 ok(!!ddraw, "Failed to create a ddraw object.\n");
3888 hr = set_display_mode(ddraw, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3889 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
3891 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3892 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %ld.\n", change_ret);
3894 ref = IDirectDraw2_Release(ddraw);
3895 ok(!ref, "Unexpected refcount %lu.\n", ref);
3897 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3898 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3899 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3900 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
3901 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3902 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3903 ret = restore_display_modes(original_modes, display_count);
3904 ok(ret, "Failed to restore display modes.\n");
3906 /* Test that mode restorations use display settings in the registry after RestoreDisplayMode() */
3907 ddraw = create_ddraw();
3908 ok(!!ddraw, "Failed to create a ddraw object.\n");
3909 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3910 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
3912 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3913 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %ld.\n", change_ret);
3915 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3916 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#lx.\n", hr);
3918 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3919 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3920 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3921 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
3922 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3923 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3925 ref = IDirectDraw2_Release(ddraw);
3926 ok(!ref, "Unexpected refcount %lu.\n", ref);
3928 done:
3929 expect_messages = NULL;
3930 DestroyWindow(window);
3931 DestroyWindow(window2);
3932 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3933 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3934 ret = restore_display_modes(original_modes, display_count);
3935 ok(ret, "Failed to restore display modes.\n");
3936 free(original_modes);
3939 static void test_coop_level_mode_set_multi(void)
3941 DEVMODEW old_devmode, devmode, devmode2, devmode3, *original_modes = NULL;
3942 unsigned int mode_idx = 0, display_idx, display_count = 0;
3943 WCHAR second_monitor_name[CCHDEVICENAME];
3944 IDirectDraw2 *ddraw1, *ddraw2;
3945 LONG change_ret;
3946 UINT w, h;
3947 HWND window;
3948 HRESULT hr;
3949 ULONG ref;
3950 BOOL ret;
3952 memset(&devmode, 0, sizeof(devmode));
3953 devmode.dmSize = sizeof(devmode);
3954 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3955 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3956 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3957 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
3958 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3959 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3961 ret = save_display_modes(&original_modes, &display_count);
3962 ok(ret, "Failed to save original display modes.\n");
3964 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3965 0, 0, 100, 100, 0, 0, 0, 0);
3966 ddraw1 = create_ddraw();
3967 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3969 /* With just a single ddraw object, the display mode is restored on
3970 * release. */
3971 hr = set_display_mode(ddraw1, 800, 600);
3972 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
3974 win_skip("Broken SetDisplayMode(), skipping test.\n");
3975 IDirectDraw2_Release(ddraw1);
3976 DestroyWindow(window);
3977 return;
3979 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3980 w = GetSystemMetrics(SM_CXSCREEN);
3981 ok(w == 800, "Got unexpected screen width %u.\n", w);
3982 h = GetSystemMetrics(SM_CYSCREEN);
3983 ok(h == 600, "Got unexpected screen height %u.\n", h);
3985 ref = IDirectDraw2_Release(ddraw1);
3986 ok(!ref, "Unexpected refcount %lu.\n", ref);
3987 w = GetSystemMetrics(SM_CXSCREEN);
3988 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3989 h = GetSystemMetrics(SM_CYSCREEN);
3990 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3992 /* When there are multiple ddraw objects, the display mode is restored to
3993 * the initial mode, before the first SetDisplayMode() call. */
3994 ddraw1 = create_ddraw();
3995 hr = set_display_mode(ddraw1, 800, 600);
3996 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3997 w = GetSystemMetrics(SM_CXSCREEN);
3998 ok(w == 800, "Got unexpected screen width %u.\n", w);
3999 h = GetSystemMetrics(SM_CYSCREEN);
4000 ok(h == 600, "Got unexpected screen height %u.\n", h);
4002 ddraw2 = create_ddraw();
4003 hr = set_display_mode(ddraw2, 640, 480);
4004 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4005 w = GetSystemMetrics(SM_CXSCREEN);
4006 ok(w == 640, "Got unexpected screen width %u.\n", w);
4007 h = GetSystemMetrics(SM_CYSCREEN);
4008 ok(h == 480, "Got unexpected screen height %u.\n", h);
4010 ref = IDirectDraw2_Release(ddraw2);
4011 ok(!ref, "Unexpected refcount %lu.\n", ref);
4012 w = GetSystemMetrics(SM_CXSCREEN);
4013 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4014 h = GetSystemMetrics(SM_CYSCREEN);
4015 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4017 ref = IDirectDraw2_Release(ddraw1);
4018 ok(!ref, "Unexpected refcount %lu.\n", ref);
4019 w = GetSystemMetrics(SM_CXSCREEN);
4020 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4021 h = GetSystemMetrics(SM_CYSCREEN);
4022 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4024 /* Regardless of release ordering. */
4025 ddraw1 = create_ddraw();
4026 hr = set_display_mode(ddraw1, 800, 600);
4027 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4028 w = GetSystemMetrics(SM_CXSCREEN);
4029 ok(w == 800, "Got unexpected screen width %u.\n", w);
4030 h = GetSystemMetrics(SM_CYSCREEN);
4031 ok(h == 600, "Got unexpected screen height %u.\n", h);
4033 ddraw2 = create_ddraw();
4034 hr = set_display_mode(ddraw2, 640, 480);
4035 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4036 w = GetSystemMetrics(SM_CXSCREEN);
4037 ok(w == 640, "Got unexpected screen width %u.\n", w);
4038 h = GetSystemMetrics(SM_CYSCREEN);
4039 ok(h == 480, "Got unexpected screen height %u.\n", h);
4041 ref = IDirectDraw2_Release(ddraw1);
4042 ok(!ref, "Unexpected refcount %lu.\n", ref);
4043 w = GetSystemMetrics(SM_CXSCREEN);
4044 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4045 h = GetSystemMetrics(SM_CYSCREEN);
4046 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4048 ref = IDirectDraw2_Release(ddraw2);
4049 ok(!ref, "Unexpected refcount %lu.\n", ref);
4050 w = GetSystemMetrics(SM_CXSCREEN);
4051 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4052 h = GetSystemMetrics(SM_CYSCREEN);
4053 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4055 /* But only for ddraw objects that called SetDisplayMode(). */
4056 ddraw1 = create_ddraw();
4057 ddraw2 = create_ddraw();
4058 hr = set_display_mode(ddraw2, 640, 480);
4059 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4060 w = GetSystemMetrics(SM_CXSCREEN);
4061 ok(w == 640, "Got unexpected screen width %u.\n", w);
4062 h = GetSystemMetrics(SM_CYSCREEN);
4063 ok(h == 480, "Got unexpected screen height %u.\n", h);
4065 ref = IDirectDraw2_Release(ddraw1);
4066 ok(!ref, "Unexpected refcount %lu.\n", ref);
4067 w = GetSystemMetrics(SM_CXSCREEN);
4068 ok(w == 640, "Got unexpected screen width %u.\n", w);
4069 h = GetSystemMetrics(SM_CYSCREEN);
4070 ok(h == 480, "Got unexpected screen height %u.\n", h);
4072 ref = IDirectDraw2_Release(ddraw2);
4073 ok(!ref, "Unexpected refcount %lu.\n", ref);
4074 w = GetSystemMetrics(SM_CXSCREEN);
4075 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4076 h = GetSystemMetrics(SM_CYSCREEN);
4077 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4079 /* If there's a ddraw object that's currently in exclusive mode, it blocks
4080 * restoring the display mode. */
4081 ddraw1 = create_ddraw();
4082 hr = set_display_mode(ddraw1, 800, 600);
4083 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4084 w = GetSystemMetrics(SM_CXSCREEN);
4085 ok(w == 800, "Got unexpected screen width %u.\n", w);
4086 h = GetSystemMetrics(SM_CYSCREEN);
4087 ok(h == 600, "Got unexpected screen height %u.\n", h);
4089 ddraw2 = create_ddraw();
4090 hr = set_display_mode(ddraw2, 640, 480);
4091 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4092 w = GetSystemMetrics(SM_CXSCREEN);
4093 ok(w == 640, "Got unexpected screen width %u.\n", w);
4094 h = GetSystemMetrics(SM_CYSCREEN);
4095 ok(h == 480, "Got unexpected screen height %u.\n", h);
4097 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4098 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
4100 ref = IDirectDraw2_Release(ddraw1);
4101 ok(!ref, "Unexpected refcount %lu.\n", ref);
4102 w = GetSystemMetrics(SM_CXSCREEN);
4103 ok(w == 640, "Got unexpected screen width %u.\n", w);
4104 h = GetSystemMetrics(SM_CYSCREEN);
4105 ok(h == 480, "Got unexpected screen height %u.\n", h);
4107 ref = IDirectDraw2_Release(ddraw2);
4108 ok(!ref, "Unexpected refcount %lu.\n", ref);
4109 w = GetSystemMetrics(SM_CXSCREEN);
4110 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4111 h = GetSystemMetrics(SM_CYSCREEN);
4112 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4114 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
4115 ddraw1 = create_ddraw();
4116 hr = set_display_mode(ddraw1, 800, 600);
4117 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4118 w = GetSystemMetrics(SM_CXSCREEN);
4119 ok(w == 800, "Got unexpected screen width %u.\n", w);
4120 h = GetSystemMetrics(SM_CYSCREEN);
4121 ok(h == 600, "Got unexpected screen height %u.\n", h);
4123 hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4124 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
4126 ddraw2 = create_ddraw();
4127 hr = set_display_mode(ddraw2, 640, 480);
4128 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
4130 ref = IDirectDraw2_Release(ddraw1);
4131 ok(!ref, "Unexpected refcount %lu.\n", ref);
4132 w = GetSystemMetrics(SM_CXSCREEN);
4133 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4134 h = GetSystemMetrics(SM_CYSCREEN);
4135 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4137 ref = IDirectDraw2_Release(ddraw2);
4138 ok(!ref, "Unexpected refcount %lu.\n", ref);
4139 w = GetSystemMetrics(SM_CXSCREEN);
4140 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4141 h = GetSystemMetrics(SM_CYSCREEN);
4142 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4144 if (display_count < 2)
4146 skip("Following tests require two monitors.\n");
4147 goto done;
4150 ret = restore_display_modes(original_modes, display_count);
4151 ok(ret, "Failed to restore display modes.\n");
4153 second_monitor_name[0] = '\0';
4154 for (display_idx = 0; display_idx < display_count; ++display_idx)
4156 if (original_modes[display_idx].dmPosition.x || original_modes[display_idx].dmPosition.y)
4158 lstrcpyW(second_monitor_name, original_modes[display_idx].dmDeviceName);
4159 break;
4162 ok(lstrlenW(second_monitor_name), "Got an empty second monitor name.\n");
4163 memset(&old_devmode, 0, sizeof(old_devmode));
4164 old_devmode.dmSize = sizeof(old_devmode);
4165 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
4166 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4168 devmode = old_devmode;
4169 while (EnumDisplaySettingsW(second_monitor_name, mode_idx++, &devmode))
4171 if (devmode.dmPelsWidth != old_devmode.dmPelsWidth
4172 || devmode.dmPelsHeight != old_devmode.dmPelsHeight)
4173 break;
4175 ok(devmode.dmPelsWidth != old_devmode.dmPelsWidth
4176 || devmode.dmPelsHeight != old_devmode.dmPelsHeight,
4177 "Failed to find a different mode for the second monitor.\n");
4179 /* Test that no mode restorations for non-primary monitors if SetDisplayMode() was not called */
4180 ddraw1 = create_ddraw();
4181 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4182 hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4183 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
4185 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4186 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4188 memset(&devmode2, 0, sizeof(devmode2));
4189 devmode2.dmSize = sizeof(devmode2);
4190 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4191 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4192 if (compare_mode_rect(&devmode2, &old_devmode))
4194 skip("Failed to change display settings of the second monitor.\n");
4195 ref = IDirectDraw2_Release(ddraw1);
4196 ok(!ref, "Unexpected refcount %lu.\n", ref);
4197 goto done;
4200 hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_NORMAL);
4201 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
4202 ref = IDirectDraw2_Release(ddraw1);
4203 ok(!ref, "Unexpected refcount %lu.\n", ref);
4205 memset(&devmode3, 0, sizeof(devmode3));
4206 devmode3.dmSize = sizeof(devmode3);
4207 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode3);
4208 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4209 ok(compare_mode_rect(&devmode3, &devmode2), "Got a different mode.\n");
4210 ret = restore_display_modes(original_modes, display_count);
4211 ok(ret, "Failed to restore display modes.\n");
4213 /* Test that mode restorations happen for non-primary monitors on ddraw releases if
4214 * SetDisplayMode() was called */
4215 ddraw1 = create_ddraw();
4216 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4217 hr = set_display_mode(ddraw1, 800, 600);
4218 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4220 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4221 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4223 ref = IDirectDraw2_Release(ddraw1);
4224 ok(!ref, "Unexpected refcount %lu.\n", ref);
4226 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4227 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4228 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4229 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4230 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4231 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4232 ret = restore_display_modes(original_modes, display_count);
4233 ok(ret, "Failed to restore display modes.\n");
4235 /* Test that mode restorations happen for non-primary monitors as well */
4236 ddraw1 = create_ddraw();
4237 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4238 hr = set_display_mode(ddraw1, 800, 600);
4239 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4241 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4242 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4244 hr = IDirectDraw2_RestoreDisplayMode(ddraw1);
4245 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#lx.\n", hr);
4247 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4248 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4249 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4250 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4251 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4252 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4254 ref = IDirectDraw2_Release(ddraw1);
4255 ok(!ref, "Unexpected refcount %lu.\n", ref);
4256 ret = restore_display_modes(original_modes, display_count);
4257 ok(ret, "Failed to restore display modes.\n");
4259 /* Test that mode restorations for non-primary monitors use display settings in the registry */
4260 ddraw1 = create_ddraw();
4261 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4262 hr = set_display_mode(ddraw1, 800, 600);
4263 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4265 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
4266 CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
4267 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4269 ref = IDirectDraw2_Release(ddraw1);
4270 ok(!ref, "Unexpected refcount %lu.\n", ref);
4272 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4273 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4274 ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
4275 "Expected resolution %lux%lu, got %lux%lu.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
4276 devmode2.dmPelsWidth, devmode2.dmPelsHeight);
4277 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4278 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4279 ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
4280 "Expected resolution %lux%lu, got %lux%lu.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
4281 devmode2.dmPelsWidth, devmode2.dmPelsHeight);
4282 ret = restore_display_modes(original_modes, display_count);
4283 ok(ret, "Failed to restore display modes.\n");
4285 /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
4286 * objects and one of them restores display mode */
4287 ddraw1 = create_ddraw();
4288 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4289 ddraw2 = create_ddraw();
4290 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4291 hr = set_display_mode(ddraw1, 800, 600);
4292 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4293 hr = set_display_mode(ddraw2, 640, 480);
4294 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4296 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4297 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4299 hr = IDirectDraw2_RestoreDisplayMode(ddraw2);
4300 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#lx.\n", hr);
4302 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4303 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4304 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4305 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4306 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4307 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4309 ref = IDirectDraw2_Release(ddraw2);
4310 ok(!ref, "Unexpected refcount %lu.\n", ref);
4311 ref = IDirectDraw2_Release(ddraw1);
4312 ok(!ref, "Unexpected refcount %lu.\n", ref);
4313 ret = restore_display_modes(original_modes, display_count);
4314 ok(ret, "Failed to restore display modes.\n");
4316 /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
4317 * objects and one of them got released */
4318 ddraw1 = create_ddraw();
4319 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4320 ddraw2 = create_ddraw();
4321 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4322 hr = set_display_mode(ddraw1, 800, 600);
4323 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4324 hr = set_display_mode(ddraw2, 640, 480);
4325 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4327 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4328 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4330 ref = IDirectDraw2_Release(ddraw2);
4331 ok(!ref, "Unexpected refcount %lu.\n", ref);
4333 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4334 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4335 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4336 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4337 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4338 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4340 ref = IDirectDraw2_Release(ddraw1);
4341 ok(!ref, "Unexpected refcount %lu.\n", ref);
4343 done:
4344 DestroyWindow(window);
4345 ret = restore_display_modes(original_modes, display_count);
4346 ok(ret, "Failed to restore display modes.\n");
4347 free(original_modes);
4350 static void test_initialize(void)
4352 IDirectDraw2 *ddraw;
4353 HRESULT hr;
4355 ddraw = create_ddraw();
4356 ok(!!ddraw, "Failed to create a ddraw object.\n");
4358 hr = IDirectDraw2_Initialize(ddraw, NULL);
4359 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#lx.\n", hr);
4360 IDirectDraw2_Release(ddraw);
4362 CoInitialize(NULL);
4363 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw2, (void **)&ddraw);
4364 ok(SUCCEEDED(hr), "Failed to create IDirectDraw2 instance, hr %#lx.\n", hr);
4365 hr = IDirectDraw2_Initialize(ddraw, NULL);
4366 ok(hr == DD_OK, "Initialize returned hr %#lx, expected DD_OK.\n", hr);
4367 hr = IDirectDraw2_Initialize(ddraw, NULL);
4368 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#lx, expected DDERR_ALREADYINITIALIZED.\n", hr);
4369 IDirectDraw2_Release(ddraw);
4370 CoUninitialize();
4373 static void test_coop_level_surf_create(void)
4375 IDirectDrawSurface *surface;
4376 IDirectDraw2 *ddraw;
4377 DDSURFACEDESC ddsd;
4378 HRESULT hr;
4380 ddraw = create_ddraw();
4381 ok(!!ddraw, "Failed to create a ddraw object.\n");
4383 memset(&ddsd, 0, sizeof(ddsd));
4384 ddsd.dwSize = sizeof(ddsd);
4385 ddsd.dwFlags = DDSD_CAPS;
4386 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4387 surface = (void *)0xdeadbeef;
4388 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4389 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#lx.\n", hr);
4390 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4392 surface = (void *)0xdeadbeef;
4393 hr = IDirectDraw2_CreateSurface(ddraw, NULL, &surface, NULL);
4394 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#lx.\n", hr);
4395 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4397 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4398 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4400 surface = (void *)0xdeadbeef;
4401 hr = IDirectDraw2_CreateSurface(ddraw, NULL, &surface, NULL);
4402 ok(hr == DDERR_INVALIDPARAMS, "Unexpected hr %#lx.\n", hr);
4403 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4405 IDirectDraw2_Release(ddraw);
4408 static void test_coop_level_multi_window(void)
4410 HWND window1, window2;
4411 IDirectDraw2 *ddraw;
4412 HRESULT hr;
4414 window1 = create_window();
4415 window2 = create_window();
4416 ddraw = create_ddraw();
4417 ok(!!ddraw, "Failed to create a ddraw object.\n");
4419 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
4420 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4421 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
4422 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4423 ok(IsWindow(window1), "Window 1 was destroyed.\n");
4424 ok(IsWindow(window2), "Window 2 was destroyed.\n");
4426 IDirectDraw2_Release(ddraw);
4427 DestroyWindow(window2);
4428 DestroyWindow(window1);
4431 static void test_clear_rect_count(void)
4433 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4434 IDirect3DMaterial2 *white, *red, *green, *blue;
4435 IDirect3DViewport2 *viewport;
4436 IDirect3DDevice2 *device;
4437 IDirectDrawSurface *rt;
4438 IDirectDraw2 *ddraw;
4439 unsigned int color;
4440 HWND window;
4441 HRESULT hr;
4443 window = create_window();
4444 ddraw = create_ddraw();
4445 ok(!!ddraw, "Failed to create a ddraw object.\n");
4446 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4448 skip("Failed to create a 3D device, skipping test.\n");
4449 IDirectDraw2_Release(ddraw);
4450 DestroyWindow(window);
4451 return;
4454 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
4455 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
4457 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
4458 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
4459 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
4460 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
4462 viewport = create_viewport(device, 0, 0, 640, 480);
4463 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
4464 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
4466 viewport_set_background(device, viewport, white);
4467 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
4468 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
4469 viewport_set_background(device, viewport, red);
4470 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
4471 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
4472 viewport_set_background(device, viewport, green);
4473 hr = IDirect3DViewport2_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
4474 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
4475 viewport_set_background(device, viewport, blue);
4476 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
4477 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
4479 color = get_surface_color(rt, 320, 240);
4480 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x000000ff, 1)),
4481 "Got unexpected color 0x%08x.\n", color);
4483 IDirectDrawSurface_Release(rt);
4484 destroy_viewport(device, viewport);
4485 destroy_material(white);
4486 destroy_material(red);
4487 destroy_material(green);
4488 destroy_material(blue);
4489 IDirect3DDevice2_Release(device);
4490 IDirectDraw2_Release(ddraw);
4491 DestroyWindow(window);
4494 static BOOL test_mode_restored(IDirectDraw2 *ddraw, HWND window)
4496 DDSURFACEDESC ddsd1, ddsd2;
4497 HRESULT hr;
4499 memset(&ddsd1, 0, sizeof(ddsd1));
4500 ddsd1.dwSize = sizeof(ddsd1);
4501 hr = IDirectDraw2_GetDisplayMode(ddraw, &ddsd1);
4502 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#lx.\n", hr);
4504 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4505 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
4506 hr = set_display_mode(ddraw, 640, 480);
4507 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4508 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4509 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
4511 memset(&ddsd2, 0, sizeof(ddsd2));
4512 ddsd2.dwSize = sizeof(ddsd2);
4513 hr = IDirectDraw2_GetDisplayMode(ddraw, &ddsd2);
4514 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#lx.\n", hr);
4515 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
4516 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#lx.\n", hr);
4518 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
4521 static void test_coop_level_versions(void)
4523 HWND window;
4524 IDirectDraw *ddraw;
4525 HRESULT hr;
4526 BOOL restored;
4527 IDirectDrawSurface *surface;
4528 IDirectDraw2 *ddraw2;
4529 DDSURFACEDESC ddsd;
4531 window = create_window();
4532 ddraw2 = create_ddraw();
4533 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4534 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
4535 restored = test_mode_restored(ddraw2, window);
4536 ok(restored, "Display mode not restored in new ddraw object\n");
4538 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
4539 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
4540 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#lx.\n", hr);
4542 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4543 ok(FAILED(hr), "SetCooperativeLevel returned %#lx, expected failure.\n", hr);
4544 restored = test_mode_restored(ddraw2, window);
4545 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
4547 /* A successful one does */
4548 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4549 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
4550 restored = test_mode_restored(ddraw2, window);
4551 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
4553 IDirectDraw_Release(ddraw);
4554 IDirectDraw2_Release(ddraw2);
4556 ddraw2 = create_ddraw();
4557 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4558 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
4559 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#lx.\n", hr);
4561 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
4562 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
4563 restored = test_mode_restored(ddraw2, window);
4564 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
4566 IDirectDraw_Release(ddraw);
4567 IDirectDraw2_Release(ddraw2);
4569 /* A failing call does not restore the ddraw2+ behavior */
4570 ddraw2 = create_ddraw();
4571 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4572 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
4573 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#lx.\n", hr);
4575 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4576 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
4577 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4578 ok(FAILED(hr), "SetCooperativeLevel returned %#lx, expected failure.\n", hr);
4579 restored = test_mode_restored(ddraw2, window);
4580 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
4582 IDirectDraw_Release(ddraw);
4583 IDirectDraw2_Release(ddraw2);
4585 /* Neither does a sequence of successful calls with the new interface */
4586 ddraw2 = create_ddraw();
4587 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4588 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
4589 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#lx.\n", hr);
4591 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4592 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
4593 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4594 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
4595 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_NORMAL);
4596 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
4598 restored = test_mode_restored(ddraw2, window);
4599 ok(!restored, "Display mode restored after ddraw1-ddraw2 SetCooperativeLevel() call sequence\n");
4600 IDirectDraw_Release(ddraw);
4601 IDirectDraw2_Release(ddraw2);
4603 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
4604 ddraw2 = create_ddraw();
4605 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4606 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
4607 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#lx.\n", hr);
4609 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_NORMAL);
4610 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
4612 memset(&ddsd, 0, sizeof(ddsd));
4613 ddsd.dwSize = sizeof(ddsd);
4614 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4615 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4616 ddsd.dwWidth = ddsd.dwHeight = 8;
4617 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4618 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#lx.\n", hr);
4619 IDirectDrawSurface_Release(surface);
4620 restored = test_mode_restored(ddraw2, window);
4621 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
4623 IDirectDraw_Release(ddraw);
4624 IDirectDraw2_Release(ddraw2);
4625 DestroyWindow(window);
4628 static void test_lighting_interface_versions(void)
4630 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4631 IDirect3DMaterial2 *emissive, *background;
4632 IDirect3DViewport2 *viewport;
4633 IDirect3DDevice2 *device;
4634 IDirectDrawSurface *rt;
4635 unsigned int color, i;
4636 IDirectDraw2 *ddraw;
4637 HWND window;
4638 HRESULT hr;
4639 D3DMATERIALHANDLE mat_handle;
4640 DWORD rs;
4641 ULONG ref;
4642 static D3DVERTEX quad[] =
4644 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4645 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4646 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4647 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4649 static D3DLVERTEX lquad[] =
4651 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4652 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4653 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4654 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4656 static D3DTLVERTEX tlquad[] =
4658 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4659 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4660 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4661 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4663 static const struct
4665 D3DVERTEXTYPE vertextype;
4666 void *data;
4667 DWORD d3drs_lighting, d3drs_specular;
4668 DWORD draw_flags;
4669 unsigned int color;
4671 tests[] =
4673 /* Lighting is enabled when D3DVT_VERTEX is used and D3DDP_DONOTLIGHT is not
4674 * set. D3DVT_VERTEX has diffuse = 0xffffffff and specular = 0x00000000, as
4675 * in later d3d versions */
4676 { D3DVT_VERTEX, quad, FALSE, FALSE, 0, 0x0000ff00},
4677 { D3DVT_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
4678 { D3DVT_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4679 { D3DVT_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4680 { D3DVT_VERTEX, quad, FALSE, TRUE, 0, 0x0000ff00},
4681 { D3DVT_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
4682 { D3DVT_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4683 { D3DVT_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4685 { D3DVT_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
4686 { D3DVT_LVERTEX, lquad, TRUE, FALSE, 0, 0x00ff0000},
4687 { D3DVT_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4688 { D3DVT_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4689 { D3DVT_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
4690 { D3DVT_LVERTEX, lquad, TRUE, TRUE, 0, 0x00ff8080},
4691 { D3DVT_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4692 { D3DVT_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4694 { D3DVT_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
4695 { D3DVT_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
4696 { D3DVT_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4697 { D3DVT_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4698 { D3DVT_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
4699 { D3DVT_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
4700 { D3DVT_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4701 { D3DVT_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4704 window = create_window();
4705 ddraw = create_ddraw();
4706 ok(!!ddraw, "Failed to create a ddraw object.\n");
4707 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4709 skip("Failed to create a 3D device, skipping test.\n");
4710 IDirectDraw2_Release(ddraw);
4711 DestroyWindow(window);
4712 return;
4715 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
4716 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
4718 viewport = create_viewport(device, 0, 0, 640, 480);
4719 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
4720 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
4722 emissive = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
4723 hr = IDirect3DMaterial2_GetHandle(emissive, device, &mat_handle);
4724 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#lx.\n", hr);
4725 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
4726 ok(SUCCEEDED(hr), "Failed to set material state, hr %#lx.\n", hr);
4727 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4728 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#lx.\n", hr);
4730 background = create_diffuse_material(device, 0.1f, 0.1f, 0.1f, 0.1f);
4731 viewport_set_background(device, viewport, background);
4733 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
4734 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#lx.\n", hr);
4735 ok(rs == TRUE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#lx, expected TRUE.\n", rs);
4737 for (i = 0; i < ARRAY_SIZE(tests); i++)
4739 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
4740 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
4742 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
4743 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#lx.\n", hr);
4744 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
4745 tests[i].d3drs_specular);
4746 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#lx.\n", hr);
4748 hr = IDirect3DDevice2_BeginScene(device);
4749 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
4750 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
4751 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
4752 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
4753 hr = IDirect3DDevice2_EndScene(device);
4754 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
4756 color = get_surface_color(rt, 320, 240);
4757 ok(compare_color(color, tests[i].color, 1),
4758 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
4759 color, tests[i].color, i);
4762 destroy_material(background);
4763 destroy_material(emissive);
4764 destroy_viewport(device, viewport);
4765 IDirectDrawSurface_Release(rt);
4766 IDirect3DDevice2_Release(device);
4767 ref = IDirectDraw2_Release(ddraw);
4768 ok(!ref, "Unexpected refcount %lu.\n", ref);
4769 DestroyWindow(window);
4772 static struct
4774 BOOL received;
4775 IDirectDraw2 *ddraw;
4776 HWND window;
4777 DWORD coop_level;
4778 } activateapp_testdata;
4780 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
4782 if (message == WM_ACTIVATEAPP)
4784 if (activateapp_testdata.ddraw)
4786 HRESULT hr;
4787 activateapp_testdata.received = FALSE;
4788 hr = IDirectDraw2_SetCooperativeLevel(activateapp_testdata.ddraw,
4789 activateapp_testdata.window, activateapp_testdata.coop_level);
4790 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#lx.\n", hr);
4791 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
4793 activateapp_testdata.received = TRUE;
4796 return DefWindowProcA(hwnd, message, wparam, lparam);
4799 static void test_coop_level_activateapp(void)
4801 IDirectDraw2 *ddraw;
4802 HRESULT hr;
4803 HWND window;
4804 WNDCLASSA wc = {0};
4805 DDSURFACEDESC ddsd;
4806 IDirectDrawSurface *surface;
4808 ddraw = create_ddraw();
4809 ok(!!ddraw, "Failed to create a ddraw object.\n");
4811 wc.lpfnWndProc = activateapp_test_proc;
4812 wc.lpszClassName = "ddraw_test_wndproc_wc";
4813 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4815 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
4816 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
4818 /* Exclusive with window already active. */
4819 SetForegroundWindow(window);
4820 activateapp_testdata.received = FALSE;
4821 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4822 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4823 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
4824 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4825 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4827 /* Exclusive with window not active. */
4828 SetForegroundWindow(GetDesktopWindow());
4829 activateapp_testdata.received = FALSE;
4830 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4831 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4832 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4833 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4834 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4836 /* Normal with window not active, then exclusive with the same window. */
4837 SetForegroundWindow(GetDesktopWindow());
4838 activateapp_testdata.received = FALSE;
4839 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4840 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4841 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
4842 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4843 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4844 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4845 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4846 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4848 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
4849 SetForegroundWindow(GetDesktopWindow());
4850 activateapp_testdata.received = FALSE;
4851 activateapp_testdata.ddraw = ddraw;
4852 activateapp_testdata.window = window;
4853 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
4854 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4855 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4856 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4857 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4858 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4860 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
4861 * succeeding. Another switch to exclusive and back to normal is needed to release the
4862 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
4863 * WM_ACTIVATEAPP messages. */
4864 activateapp_testdata.ddraw = NULL;
4865 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4866 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4867 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4868 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4870 /* Setting DDSCL_NORMAL with recursive invocation. */
4871 SetForegroundWindow(GetDesktopWindow());
4872 activateapp_testdata.received = FALSE;
4873 activateapp_testdata.ddraw = ddraw;
4874 activateapp_testdata.window = window;
4875 activateapp_testdata.coop_level = DDSCL_NORMAL;
4876 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4877 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4878 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4880 /* DDraw is in exclusive mode now. */
4881 memset(&ddsd, 0, sizeof(ddsd));
4882 ddsd.dwSize = sizeof(ddsd);
4883 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4884 ddsd.dwBackBufferCount = 1;
4885 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4886 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4887 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
4888 IDirectDrawSurface_Release(surface);
4890 /* Recover again, just to be sure. */
4891 activateapp_testdata.ddraw = NULL;
4892 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4893 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4894 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4895 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4897 DestroyWindow(window);
4898 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
4899 IDirectDraw2_Release(ddraw);
4902 struct format_support_check
4904 const DDPIXELFORMAT *format;
4905 BOOL supported;
4908 static HRESULT WINAPI test_unsupported_formats_cb(DDSURFACEDESC *desc, void *ctx)
4910 struct format_support_check *format = ctx;
4912 if (!memcmp(format->format, &desc->ddpfPixelFormat, sizeof(*format->format)))
4914 format->supported = TRUE;
4915 return DDENUMRET_CANCEL;
4918 return DDENUMRET_OK;
4921 static void test_unsupported_formats(void)
4923 HRESULT hr;
4924 BOOL expect_success;
4925 HWND window;
4926 IDirectDraw2 *ddraw;
4927 IDirect3DDevice2 *device;
4928 IDirectDrawSurface *surface;
4929 DDSURFACEDESC ddsd;
4930 unsigned int i, j;
4931 DWORD expected_caps;
4932 static const struct
4934 const char *name;
4935 DDPIXELFORMAT fmt;
4937 formats[] =
4940 "D3DFMT_A8R8G8B8",
4942 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
4943 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
4947 "D3DFMT_P8",
4949 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
4950 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
4954 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
4956 window = create_window();
4957 ddraw = create_ddraw();
4958 ok(!!ddraw, "Failed to create a ddraw object.\n");
4959 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4961 skip("Failed to create a 3D device, skipping test.\n");
4962 IDirectDraw2_Release(ddraw);
4963 DestroyWindow(window);
4964 return;
4967 for (i = 0; i < ARRAY_SIZE(formats); i++)
4969 struct format_support_check check = {&formats[i].fmt, FALSE};
4970 hr = IDirect3DDevice2_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
4971 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
4973 for (j = 0; j < ARRAY_SIZE(caps); j++)
4975 memset(&ddsd, 0, sizeof(ddsd));
4976 ddsd.dwSize = sizeof(ddsd);
4977 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4978 ddsd.ddpfPixelFormat = formats[i].fmt;
4979 ddsd.dwWidth = 4;
4980 ddsd.dwHeight = 4;
4981 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
4983 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
4984 expect_success = FALSE;
4985 else
4986 expect_success = TRUE;
4988 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4989 ok(SUCCEEDED(hr) == expect_success,
4990 "Got unexpected hr %#lx for format %s, caps %#lx, expected %s.\n",
4991 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
4992 if (FAILED(hr))
4993 continue;
4995 memset(&ddsd, 0, sizeof(ddsd));
4996 ddsd.dwSize = sizeof(ddsd);
4997 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
4998 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
5000 if (caps[j] & DDSCAPS_VIDEOMEMORY)
5001 expected_caps = DDSCAPS_VIDEOMEMORY;
5002 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
5003 expected_caps = DDSCAPS_SYSTEMMEMORY;
5004 else if (check.supported)
5005 expected_caps = DDSCAPS_VIDEOMEMORY;
5006 else
5007 expected_caps = DDSCAPS_SYSTEMMEMORY;
5009 ok(ddsd.ddsCaps.dwCaps & expected_caps,
5010 "Expected caps %#lx, format %s, input caps %#lx.\n",
5011 expected_caps, formats[i].name, caps[j]);
5013 IDirectDrawSurface_Release(surface);
5017 IDirect3DDevice2_Release(device);
5018 IDirectDraw2_Release(ddraw);
5019 DestroyWindow(window);
5022 static void test_rt_caps(const GUID *device_guid)
5024 DWORD fourcc_codes[64], fourcc_code_count;
5025 PALETTEENTRY palette_entries[256];
5026 IDirectDrawPalette *palette;
5027 IDirect3DDevice2 *device;
5028 BOOL software_device;
5029 IDirectDraw2 *ddraw;
5030 DWORD z_depth = 0;
5031 IDirect3D2 *d3d;
5032 DDCAPS hal_caps;
5033 unsigned int i;
5034 ULONG refcount;
5035 HWND window;
5036 HRESULT hr;
5038 static const DDPIXELFORMAT p8_fmt =
5040 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5041 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
5043 static const DDPIXELFORMAT fourcc_fmt =
5045 .dwSize = sizeof(DDPIXELFORMAT),
5046 .dwFlags = DDPF_FOURCC,
5047 .dwFourCC = MAKEFOURCC('Y','U','Y','2'),
5050 static const struct
5052 const DDPIXELFORMAT *pf;
5053 DWORD caps_in;
5054 HRESULT create_device_hr;
5055 HRESULT set_rt_hr;
5056 HRESULT alternative_set_rt_hr;
5057 BOOL create_may_fail;
5059 test_data[] =
5062 NULL,
5063 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5064 D3D_OK,
5065 D3D_OK,
5066 D3D_OK,
5067 FALSE,
5070 NULL,
5071 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5072 D3D_OK,
5073 D3D_OK,
5074 D3D_OK,
5075 FALSE,
5078 NULL,
5079 DDSCAPS_OFFSCREENPLAIN,
5080 DDERR_INVALIDCAPS,
5081 DDERR_INVALIDCAPS,
5082 DDERR_INVALIDCAPS,
5083 FALSE,
5086 NULL,
5087 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5088 D3DERR_SURFACENOTINVIDMEM,
5089 D3D_OK,
5090 D3D_OK,
5091 FALSE,
5094 NULL,
5095 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5096 DDERR_INVALIDCAPS,
5097 DDERR_INVALIDCAPS,
5098 DDERR_INVALIDCAPS,
5099 FALSE,
5102 NULL,
5103 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5104 D3D_OK,
5105 D3D_OK,
5106 D3D_OK,
5107 FALSE,
5110 NULL,
5111 DDSCAPS_3DDEVICE,
5112 D3D_OK,
5113 D3D_OK,
5114 D3D_OK,
5115 FALSE,
5118 NULL,
5120 DDERR_INVALIDCAPS,
5121 DDERR_INVALIDCAPS,
5122 DDERR_INVALIDCAPS,
5123 FALSE,
5126 NULL,
5127 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5128 D3DERR_SURFACENOTINVIDMEM,
5129 D3D_OK,
5130 D3D_OK,
5131 FALSE,
5134 NULL,
5135 DDSCAPS_SYSTEMMEMORY,
5136 DDERR_INVALIDCAPS,
5137 DDERR_INVALIDCAPS,
5138 DDERR_INVALIDCAPS,
5139 FALSE,
5142 &p8_fmt,
5144 DDERR_INVALIDCAPS,
5145 DDERR_INVALIDCAPS,
5146 DDERR_INVALIDCAPS,
5147 FALSE,
5150 &p8_fmt,
5151 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5152 DDERR_NOPALETTEATTACHED,
5153 DDERR_INVALIDCAPS,
5154 DDERR_INVALIDCAPS,
5155 FALSE,
5158 &p8_fmt,
5159 DDSCAPS_OFFSCREENPLAIN,
5160 DDERR_INVALIDCAPS,
5161 DDERR_INVALIDCAPS,
5162 DDERR_INVALIDCAPS,
5163 FALSE,
5166 &p8_fmt,
5167 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5168 DDERR_NOPALETTEATTACHED,
5169 DDERR_INVALIDCAPS,
5170 DDERR_INVALIDCAPS,
5171 FALSE,
5174 &p8_fmt,
5175 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5176 DDERR_INVALIDCAPS,
5177 DDERR_INVALIDCAPS,
5178 DDERR_INVALIDCAPS,
5179 FALSE,
5182 NULL,
5183 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
5184 DDERR_INVALIDCAPS,
5185 DDERR_INVALIDPIXELFORMAT,
5186 DDERR_INVALIDCAPS,
5187 TRUE /* AMD Evergreen */,
5190 NULL,
5191 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5192 DDERR_INVALIDCAPS,
5193 DDERR_INVALIDPIXELFORMAT,
5194 DDERR_INVALIDCAPS,
5195 FALSE,
5198 NULL,
5199 DDSCAPS_ZBUFFER,
5200 DDERR_INVALIDCAPS,
5201 DDERR_INVALIDCAPS,
5202 DDERR_INVALIDCAPS,
5203 FALSE,
5206 NULL,
5207 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5208 DDERR_INVALIDCAPS,
5209 DDERR_INVALIDPIXELFORMAT,
5210 DDERR_INVALIDPIXELFORMAT,
5211 TRUE /* Nvidia Kepler */,
5214 NULL,
5215 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5216 DDERR_INVALIDCAPS,
5217 DDERR_INVALIDCAPS,
5218 DDERR_INVALIDCAPS,
5219 TRUE /* Nvidia Kepler */,
5222 &fourcc_fmt,
5223 DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_OFFSCREENPLAIN,
5224 DDERR_INVALIDCAPS,
5225 DDERR_INVALIDCAPS,
5226 DDERR_INVALIDCAPS,
5230 software_device = is_software_device_type(device_guid);
5232 window = create_window();
5233 ddraw = create_ddraw();
5234 ok(!!ddraw, "Failed to create a ddraw object.\n");
5235 if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid, NULL)))
5237 skip("Failed to create a 3D device, skipping test.\n");
5238 IDirectDraw2_Release(ddraw);
5239 DestroyWindow(window);
5240 return;
5242 z_depth = get_device_z_depth(device);
5243 ok(!!z_depth, "Failed to get device z depth.\n");
5244 IDirect3DDevice2_Release(device);
5246 if (FAILED(IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
5248 skip("D3D interface is not available, skipping test.\n");
5249 goto done;
5252 memset(palette_entries, 0, sizeof(palette_entries));
5253 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
5254 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
5256 memset(&hal_caps, 0, sizeof(hal_caps));
5257 hal_caps.dwSize = sizeof(hal_caps);
5258 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
5259 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
5261 fourcc_code_count = ARRAY_SIZE(fourcc_codes);
5262 hr = IDirectDraw4_GetFourCCCodes(ddraw, &fourcc_code_count, fourcc_codes);
5263 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
5265 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5267 IDirectDrawSurface *surface, *rt, *expected_rt, *tmp;
5268 DWORD caps_in, expected_caps;
5269 DDSURFACEDESC surface_desc;
5270 IDirect3DDevice2 *device;
5271 HRESULT expected_hr;
5273 caps_in = test_data[i].caps_in;
5275 memset(&surface_desc, 0, sizeof(surface_desc));
5276 surface_desc.dwSize = sizeof(surface_desc);
5277 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5278 surface_desc.ddsCaps.dwCaps = caps_in;
5279 if (test_data[i].pf)
5281 if (test_data[i].pf->dwFlags & DDPF_FOURCC)
5283 unsigned int j;
5285 for (j = 0; j < fourcc_code_count; ++j)
5287 if (test_data[i].pf->dwFourCC == fourcc_codes[j])
5288 break;
5290 if (j == fourcc_code_count)
5292 skip("Fourcc format %#lx is not supported, skipping test.\n", test_data[i].pf->dwFourCC);
5293 continue;
5296 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5297 surface_desc.ddpfPixelFormat = *test_data[i].pf;
5299 if (caps_in & DDSCAPS_ZBUFFER)
5301 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
5302 surface_desc.dwZBufferBitDepth = z_depth;
5304 if (caps_in & DDSCAPS_FLIP)
5306 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5307 surface_desc.dwBackBufferCount = 1;
5309 surface_desc.dwWidth = 640;
5310 surface_desc.dwHeight = 480;
5311 if ((caps_in & DDSCAPS_VIDEOMEMORY) && !(hal_caps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
5312 expected_hr = DDERR_NODIRECTDRAWHW;
5313 else
5314 expected_hr = DD_OK;
5315 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5316 ok(hr == expected_hr || broken(test_data[i].create_may_fail
5317 || (software_device && test_data[i].pf == &p8_fmt && hr == DDERR_INVALIDPIXELFORMAT)),
5318 "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
5319 if (FAILED(hr))
5320 continue;
5322 memset(&surface_desc, 0, sizeof(surface_desc));
5323 surface_desc.dwSize = sizeof(surface_desc);
5324 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
5326 if ((caps_in & DDSCAPS_SYSTEMMEMORY) || !(hal_caps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
5327 expected_caps = caps_in | DDSCAPS_SYSTEMMEMORY;
5328 else
5329 expected_caps = caps_in | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
5331 if (caps_in & DDSCAPS_FLIP)
5332 expected_caps |= DDSCAPS_FRONTBUFFER;
5334 ok(surface_desc.ddsCaps.dwCaps == expected_caps || (test_data[i].pf == &p8_fmt
5335 && surface_desc.ddsCaps.dwCaps == (caps_in | DDSCAPS_SYSTEMMEMORY))
5336 || (software_device && caps_in & DDSCAPS_ZBUFFER
5337 && surface_desc.ddsCaps.dwCaps == (caps_in | DDSCAPS_SYSTEMMEMORY)),
5338 "Got unexpected caps %#lx, expected %#lx, test %u, software_device %u.\n",
5339 surface_desc.ddsCaps.dwCaps, expected_caps, i, software_device);
5341 hr = IDirect3D2_CreateDevice(d3d, device_guid, surface, &device);
5343 ok((!software_device && hr == test_data[i].create_device_hr)
5344 || (software_device && (hr == (test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM
5345 ? DD_OK : test_data[i].create_device_hr))),
5346 "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
5348 if (FAILED(hr))
5350 if (hr == DDERR_NOPALETTEATTACHED)
5352 hr = IDirectDrawSurface_SetPalette(surface, palette);
5353 ok(hr == DD_OK, "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
5354 hr = IDirect3D2_CreateDevice(d3d, device_guid, surface, &device);
5355 if (software_device)
5356 todo_wine
5357 ok(hr == DD_OK, "Got unexpected hr %#lx, test %u, software_device %u.\n",
5358 hr, i, software_device);
5359 else if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5360 ok(hr == DDERR_INVALIDPIXELFORMAT, "Got unexpected hr %#lx, test %u, software_device %u.\n",
5361 hr, i, software_device);
5362 else
5363 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Got unexpected hr %#lx, test %u, software_device %u.\n",
5364 hr, i, software_device);
5366 if (hr == DD_OK)
5368 refcount = IDirect3DDevice2_Release(device);
5369 ok(!refcount, "Test %u: The device was not properly freed, refcount %lu.\n", i, refcount);
5372 IDirectDrawSurface_Release(surface);
5374 memset(&surface_desc, 0, sizeof(surface_desc));
5375 surface_desc.dwSize = sizeof(surface_desc);
5376 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5377 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5378 surface_desc.dwWidth = 640;
5379 surface_desc.dwHeight = 480;
5380 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5381 ok(hr == DD_OK, "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
5383 hr = IDirect3D2_CreateDevice(d3d, device_guid, surface, &device);
5384 ok(hr == DD_OK, "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
5387 memset(&surface_desc, 0, sizeof(surface_desc));
5388 surface_desc.dwSize = sizeof(surface_desc);
5389 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5390 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5391 if (test_data[i].pf)
5393 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5394 surface_desc.ddpfPixelFormat = *test_data[i].pf;
5396 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
5398 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
5399 surface_desc.dwZBufferBitDepth = z_depth;
5401 if (caps_in & DDSCAPS_FLIP)
5403 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5404 surface_desc.dwBackBufferCount = 1;
5406 surface_desc.dwWidth = 640;
5407 surface_desc.dwHeight = 480;
5408 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &rt, NULL);
5409 ok(hr == DD_OK, "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
5411 hr = IDirect3DDevice2_SetRenderTarget(device, rt, 0);
5412 ok(hr == test_data[i].set_rt_hr || (software_device && hr == DDERR_NOPALETTEATTACHED)
5413 || broken(hr == test_data[i].alternative_set_rt_hr),
5414 "Got unexpected hr %#lx, test %u, software_device %u.\n",
5415 hr, i, software_device);
5417 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
5418 expected_rt = rt;
5419 else
5420 expected_rt = surface;
5422 /* It appears the surface is set as render target in this case, but no
5423 * reference is taken. */
5424 if (hr == DDERR_INVALIDPIXELFORMAT)
5426 refcount = IDirectDrawSurface_AddRef(rt);
5427 ok(refcount == 2, "Test %u: Got unexpected refcount %lu.\n", i, refcount);
5430 hr = IDirect3DDevice2_GetRenderTarget(device, &tmp);
5431 ok(hr == DD_OK, "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
5432 ok(tmp == expected_rt, "Got unexpected rt %p, test %u, software_device %u.\n", tmp, i, software_device);
5434 IDirectDrawSurface_Release(tmp);
5435 IDirectDrawSurface_Release(rt);
5436 refcount = IDirect3DDevice2_Release(device);
5437 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
5438 refcount = IDirectDrawSurface_Release(surface);
5439 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
5442 IDirectDrawPalette_Release(palette);
5443 IDirect3D2_Release(d3d);
5445 done:
5446 refcount = IDirectDraw2_Release(ddraw);
5447 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
5448 DestroyWindow(window);
5451 static void test_primary_caps(void)
5453 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5454 IDirectDrawSurface *surface;
5455 DDSURFACEDESC surface_desc;
5456 IDirectDraw2 *ddraw;
5457 unsigned int i;
5458 ULONG refcount;
5459 HWND window;
5460 HRESULT hr;
5462 static const struct
5464 DWORD coop_level;
5465 DWORD caps_in;
5466 DWORD back_buffer_count;
5467 HRESULT hr;
5468 DWORD caps_out;
5470 test_data[] =
5473 DDSCL_NORMAL,
5474 DDSCAPS_PRIMARYSURFACE,
5475 ~0u,
5476 DD_OK,
5477 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
5480 DDSCL_NORMAL,
5481 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
5482 ~0u,
5483 DDERR_INVALIDCAPS,
5484 ~0u,
5487 DDSCL_NORMAL,
5488 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
5489 ~0u,
5490 DDERR_INVALIDCAPS,
5491 ~0u,
5494 DDSCL_NORMAL,
5495 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
5496 ~0u,
5497 DDERR_INVALIDCAPS,
5498 ~0u,
5501 DDSCL_NORMAL,
5502 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
5503 ~0u,
5504 DDERR_INVALIDCAPS,
5505 ~0u,
5508 DDSCL_NORMAL,
5509 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
5510 ~0u,
5511 DDERR_INVALIDCAPS,
5512 ~0u,
5515 DDSCL_NORMAL,
5516 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5517 ~0u,
5518 DDERR_INVALIDCAPS,
5519 ~0u,
5522 DDSCL_NORMAL,
5523 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5525 DDERR_INVALIDCAPS,
5526 ~0u,
5529 DDSCL_NORMAL,
5530 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5532 DDERR_NOEXCLUSIVEMODE,
5533 ~0u,
5536 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5537 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5539 DDERR_INVALIDCAPS,
5540 ~0u,
5543 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5544 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5546 DD_OK,
5547 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
5550 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5551 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
5553 DDERR_INVALIDCAPS,
5554 ~0u,
5557 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5558 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
5560 DDERR_INVALIDCAPS,
5561 ~0u,
5565 window = create_window();
5566 ddraw = create_ddraw();
5567 ok(!!ddraw, "Failed to create a ddraw object.\n");
5569 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5571 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
5572 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
5574 memset(&surface_desc, 0, sizeof(surface_desc));
5575 surface_desc.dwSize = sizeof(surface_desc);
5576 surface_desc.dwFlags = DDSD_CAPS;
5577 if (test_data[i].back_buffer_count != ~0u)
5578 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5579 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5580 surface_desc.dwBackBufferCount = test_data[i].back_buffer_count;
5581 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5582 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n", i, hr, test_data[i].hr);
5583 if (FAILED(hr))
5584 continue;
5586 memset(&surface_desc, 0, sizeof(surface_desc));
5587 surface_desc.dwSize = sizeof(surface_desc);
5588 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
5589 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#lx.\n", i, hr);
5590 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
5591 "Test %u: Got unexpected caps %#lx, expected %#lx.\n",
5592 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5594 IDirectDrawSurface_Release(surface);
5597 refcount = IDirectDraw2_Release(ddraw);
5598 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
5599 DestroyWindow(window);
5602 static void test_surface_lock(void)
5604 IDirectDraw2 *ddraw;
5605 IDirectDrawSurface *surface;
5606 IDirect3DDevice2 *device;
5607 HRESULT hr;
5608 HWND window;
5609 unsigned int i;
5610 DDSURFACEDESC ddsd;
5611 ULONG refcount;
5612 DWORD z_depth = 0;
5613 static const struct
5615 DWORD caps;
5616 const char *name;
5618 tests[] =
5621 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
5622 "videomemory offscreenplain"
5625 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5626 "systemmemory offscreenplain"
5629 DDSCAPS_PRIMARYSURFACE,
5630 "primary"
5633 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5634 "videomemory texture"
5637 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
5638 "systemmemory texture"
5641 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5642 "render target"
5645 DDSCAPS_ZBUFFER,
5646 "Z buffer"
5650 window = create_window();
5651 ddraw = create_ddraw();
5652 ok(!!ddraw, "Failed to create a ddraw object.\n");
5653 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
5655 skip("Failed to create a 3D device, skipping test.\n");
5656 IDirectDraw2_Release(ddraw);
5657 DestroyWindow(window);
5658 return;
5660 z_depth = get_device_z_depth(device);
5661 ok(!!z_depth, "Failed to get device z depth.\n");
5662 IDirect3DDevice2_Release(device);
5664 for (i = 0; i < ARRAY_SIZE(tests); i++)
5666 memset(&ddsd, 0, sizeof(ddsd));
5667 ddsd.dwSize = sizeof(ddsd);
5668 ddsd.dwFlags = DDSD_CAPS;
5669 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
5671 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5672 ddsd.dwWidth = 64;
5673 ddsd.dwHeight = 64;
5675 if (tests[i].caps & DDSCAPS_ZBUFFER)
5677 ddsd.dwFlags |= DDSD_ZBUFFERBITDEPTH;
5678 ddsd.dwZBufferBitDepth = z_depth;
5680 ddsd.ddsCaps.dwCaps = tests[i].caps;
5682 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5683 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#lx.\n", tests[i].name, hr);
5685 memset(&ddsd, 0, sizeof(ddsd));
5686 ddsd.dwSize = sizeof(ddsd);
5687 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5688 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#lx.\n", tests[i].name, hr);
5689 if (SUCCEEDED(hr))
5691 hr = IDirectDrawSurface_Unlock(surface, NULL);
5692 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#lx.\n", tests[i].name, hr);
5695 memset(&ddsd, 0, sizeof(ddsd));
5696 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5697 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx, type %s.\n", hr, tests[i].name);
5699 IDirectDrawSurface_Release(surface);
5702 refcount = IDirectDraw2_Release(ddraw);
5703 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
5704 DestroyWindow(window);
5707 static void test_surface_discard(void)
5709 IDirectDraw2 *ddraw;
5710 IDirect3DDevice2 *device;
5711 HRESULT hr;
5712 HWND window;
5713 DDSURFACEDESC ddsd;
5714 IDirectDrawSurface *surface, *target;
5715 void *addr;
5716 static const struct
5718 DWORD caps;
5719 BOOL discard;
5721 tests[] =
5723 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, TRUE},
5724 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, FALSE},
5725 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, TRUE},
5726 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, FALSE},
5728 unsigned int i;
5730 window = create_window();
5732 for (i = 0; i < ARRAY_SIZE(tests); i++)
5734 BOOL discarded;
5736 /* Sigh. Anything other than the first run of the loop randomly fails with
5737 * DDERR_SURFACELOST on my Radeon Pro 560 on Win10 19.09. Most of the time
5738 * the blit fails, but with sleeps added between surface creation and lock
5739 * the lock can fail too. Interestingly ddraw claims the render target has
5740 * been lost, not the test surface.
5742 * Recreating ddraw every iteration seems to fix this. */
5743 ddraw = create_ddraw();
5744 ok(!!ddraw, "Failed to create a ddraw object.\n");
5745 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
5747 skip("Failed to create a 3D device, skipping test.\n");
5748 DestroyWindow(window);
5749 IDirectDraw2_Release(ddraw);
5750 return;
5753 hr = IDirect3DDevice2_GetRenderTarget(device, &target);
5754 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
5756 memset(&ddsd, 0, sizeof(ddsd));
5757 ddsd.dwSize = sizeof(ddsd);
5758 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5759 ddsd.ddsCaps.dwCaps = tests[i].caps;
5760 ddsd.dwWidth = 64;
5761 ddsd.dwHeight = 64;
5762 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5763 if (FAILED(hr))
5765 skip("Failed to create surface, skipping.\n");
5766 continue;
5769 memset(&ddsd, 0, sizeof(ddsd));
5770 ddsd.dwSize = sizeof(ddsd);
5771 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5772 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
5773 addr = ddsd.lpSurface;
5774 hr = IDirectDrawSurface_Unlock(surface, NULL);
5775 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
5777 memset(&ddsd, 0, sizeof(ddsd));
5778 ddsd.dwSize = sizeof(ddsd);
5779 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
5780 ok(SUCCEEDED(hr) , "Failed to lock surface, hr %#lx.\n", hr);
5781 discarded = ddsd.lpSurface != addr;
5782 hr = IDirectDrawSurface_Unlock(surface, NULL);
5783 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
5785 hr = IDirectDrawSurface_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
5786 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
5788 memset(&ddsd, 0, sizeof(ddsd));
5789 ddsd.dwSize = sizeof(ddsd);
5790 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
5791 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
5792 discarded |= ddsd.lpSurface != addr;
5793 hr = IDirectDrawSurface_Unlock(surface, NULL);
5794 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
5796 IDirectDrawSurface_Release(surface);
5798 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
5799 * AMD r500, evergreen). Windows XP, at least on AMD r200, never changes the pointer. */
5800 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
5802 IDirectDrawSurface_Release(target);
5803 IDirect3DDevice2_Release(device);
5804 IDirectDraw2_Release(ddraw);
5807 DestroyWindow(window);
5810 static void test_flip(void)
5812 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5813 IDirectDrawSurface *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
5814 DDSCAPS caps = {DDSCAPS_FLIP};
5815 DDSURFACEDESC surface_desc;
5816 unsigned int color, i;
5817 BOOL sysmem_primary;
5818 IDirectDraw2 *ddraw;
5819 DWORD expected_caps;
5820 ULONG refcount;
5821 HWND window;
5822 HRESULT hr;
5824 static const struct
5826 const char *name;
5827 DWORD caps;
5829 test_data[] =
5831 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
5832 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
5833 {"TEXTURE", DDSCAPS_TEXTURE},
5836 window = create_window();
5837 ddraw = create_ddraw();
5838 ok(!!ddraw, "Failed to create a ddraw object.\n");
5840 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5841 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
5843 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5845 /* Creating a flippable texture induces a BSoD on some versions of the
5846 * Intel graphics driver. At least Intel GMA 950 with driver version
5847 * 6.14.10.4926 on Windows XP SP3 is affected. */
5848 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
5850 win_skip("Skipping flippable texture test.\n");
5851 continue;
5854 memset(&surface_desc, 0, sizeof(surface_desc));
5855 surface_desc.dwSize = sizeof(surface_desc);
5856 surface_desc.dwFlags = DDSD_CAPS;
5857 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
5858 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5859 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
5860 surface_desc.dwWidth = 512;
5861 surface_desc.dwHeight = 512;
5862 surface_desc.dwBackBufferCount = 3;
5863 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5864 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5866 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
5867 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5868 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5869 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5871 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
5872 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
5873 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5874 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5876 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
5877 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5878 todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
5879 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#lx.\n", test_data[i].name, hr);
5880 if (FAILED(hr))
5881 continue;
5883 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
5884 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#lx.\n", test_data[i].name, hr);
5885 hr = IDirectDrawSurface_IsLost(frontbuffer);
5886 ok(hr == DD_OK, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5887 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
5888 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
5889 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5890 else
5891 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
5892 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5893 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#lx.\n", test_data[i].name, hr);
5894 hr = IDirectDrawSurface_IsLost(frontbuffer);
5895 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5896 hr = restore_surfaces(ddraw);
5897 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#lx.\n", test_data[i].name, hr);
5899 memset(&surface_desc, 0, sizeof(surface_desc));
5900 surface_desc.dwSize = sizeof(surface_desc);
5901 hr = IDirectDrawSurface_GetSurfaceDesc(frontbuffer, &surface_desc);
5902 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#lx.\n", test_data[i].name, hr);
5903 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
5904 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
5905 expected_caps |= DDSCAPS_VISIBLE;
5906 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5907 "%s: Got unexpected caps %#lx.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5908 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
5910 hr = IDirectDrawSurface_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
5911 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#lx.\n", test_data[i].name, hr);
5912 memset(&surface_desc, 0, sizeof(surface_desc));
5913 surface_desc.dwSize = sizeof(surface_desc);
5914 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer1, &surface_desc);
5915 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#lx.\n", test_data[i].name, hr);
5916 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %lu.\n",
5917 test_data[i].name, surface_desc.dwBackBufferCount);
5918 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
5919 expected_caps |= DDSCAPS_BACKBUFFER;
5920 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5921 "%s: Got unexpected caps %#lx.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5923 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
5924 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#lx.\n", test_data[i].name, hr);
5925 memset(&surface_desc, 0, sizeof(surface_desc));
5926 surface_desc.dwSize = sizeof(surface_desc);
5927 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer2, &surface_desc);
5928 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#lx.\n", test_data[i].name, hr);
5929 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %lu.\n",
5930 test_data[i].name, surface_desc.dwBackBufferCount);
5931 expected_caps &= ~DDSCAPS_BACKBUFFER;
5932 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5933 "%s: Got unexpected caps %#lx.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5935 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
5936 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#lx.\n", test_data[i].name, hr);
5937 memset(&surface_desc, 0, sizeof(surface_desc));
5938 surface_desc.dwSize = sizeof(surface_desc);
5939 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer3, &surface_desc);
5940 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#lx.\n", test_data[i].name, hr);
5941 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %lu.\n",
5942 test_data[i].name, surface_desc.dwBackBufferCount);
5943 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5944 "%s: Got unexpected caps %#lx.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5946 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer3, &caps, &surface);
5947 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#lx.\n", test_data[i].name, hr);
5948 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
5949 test_data[i].name, surface, frontbuffer);
5950 IDirectDrawSurface_Release(surface);
5952 memset(&surface_desc, 0, sizeof(surface_desc));
5953 surface_desc.dwSize = sizeof(surface_desc);
5954 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5955 surface_desc.ddsCaps.dwCaps = 0;
5956 surface_desc.dwWidth = 640;
5957 surface_desc.dwHeight = 480;
5958 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5959 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#lx.\n", test_data[i].name, hr);
5960 hr = IDirectDrawSurface_Flip(frontbuffer, surface, DDFLIP_WAIT);
5961 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5962 IDirectDrawSurface_Release(surface);
5964 hr = IDirectDrawSurface_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
5965 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5966 hr = IDirectDrawSurface_Flip(backbuffer1, NULL, DDFLIP_WAIT);
5967 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5968 hr = IDirectDrawSurface_Flip(backbuffer2, NULL, DDFLIP_WAIT);
5969 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5970 hr = IDirectDrawSurface_Flip(backbuffer3, NULL, DDFLIP_WAIT);
5971 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
5973 /* The Nvidia Geforce 7 driver cannot do a color fill on a texture backbuffer after
5974 * the backbuffer has been locked or GetSurfaceDesc has been called. Do it ourselves
5975 * as a workaround. */
5976 fill_surface(backbuffer1, 0xffff0000);
5977 fill_surface(backbuffer2, 0xff00ff00);
5978 fill_surface(backbuffer3, 0xff0000ff);
5980 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
5981 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
5982 color = get_surface_color(backbuffer1, 320, 240);
5983 /* The testbot seems to just copy the contents of one surface to all the
5984 * others, instead of properly flipping. */
5985 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
5986 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5987 color = get_surface_color(backbuffer2, 320, 240);
5988 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5989 fill_surface(backbuffer3, 0xffff0000);
5991 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
5992 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
5993 color = get_surface_color(backbuffer1, 320, 240);
5994 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
5995 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5996 color = get_surface_color(backbuffer2, 320, 240);
5997 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5998 fill_surface(backbuffer3, 0xff00ff00);
6000 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6001 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
6002 color = get_surface_color(backbuffer1, 320, 240);
6003 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6004 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6005 color = get_surface_color(backbuffer2, 320, 240);
6006 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6007 fill_surface(backbuffer3, 0xff0000ff);
6009 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
6010 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
6011 color = get_surface_color(backbuffer2, 320, 240);
6012 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6013 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6014 color = get_surface_color(backbuffer3, 320, 240);
6015 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6016 fill_surface(backbuffer1, 0xffff0000);
6018 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
6019 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
6020 color = get_surface_color(backbuffer1, 320, 240);
6021 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6022 color = get_surface_color(backbuffer3, 320, 240);
6023 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6024 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6025 fill_surface(backbuffer2, 0xff00ff00);
6027 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
6028 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
6029 color = get_surface_color(backbuffer1, 320, 240);
6030 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6031 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6032 color = get_surface_color(backbuffer2, 320, 240);
6033 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6035 IDirectDrawSurface_Release(backbuffer3);
6036 IDirectDrawSurface_Release(backbuffer2);
6037 IDirectDrawSurface_Release(backbuffer1);
6038 IDirectDrawSurface_Release(frontbuffer);
6041 refcount = IDirectDraw2_Release(ddraw);
6042 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
6043 DestroyWindow(window);
6046 static void reset_ddsd(DDSURFACEDESC *ddsd)
6048 memset(ddsd, 0, sizeof(*ddsd));
6049 ddsd->dwSize = sizeof(*ddsd);
6052 static void test_set_surface_desc(void)
6054 IDirectDraw2 *ddraw;
6055 HWND window;
6056 HRESULT hr;
6057 DDSURFACEDESC ddsd;
6058 IDirectDrawSurface *surface;
6059 IDirectDrawSurface3 *surface3;
6060 BYTE data[16*16*4];
6061 ULONG ref;
6062 unsigned int i;
6063 static const struct
6065 DWORD caps;
6066 BOOL supported;
6067 const char *name;
6069 invalid_caps_tests[] =
6071 {DDSCAPS_VIDEOMEMORY, FALSE, "videomemory plain"},
6072 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, TRUE, "systemmemory texture"},
6073 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, FALSE, "systemmemory primary"},
6076 window = create_window();
6077 ddraw = create_ddraw();
6078 ok(!!ddraw, "Failed to create a ddraw object.\n");
6079 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6080 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6082 reset_ddsd(&ddsd);
6083 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6084 ddsd.dwWidth = 8;
6085 ddsd.dwHeight = 8;
6086 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
6087 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
6088 ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
6089 ddsd.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
6090 ddsd.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
6091 ddsd.ddpfPixelFormat.dwBBitMask = 0x000000ff;
6092 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6094 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
6095 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6097 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
6098 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#lx.\n", hr);
6099 IDirectDrawSurface_Release(surface);
6101 reset_ddsd(&ddsd);
6102 ddsd.dwFlags = DDSD_LPSURFACE;
6103 ddsd.lpSurface = data;
6104 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6105 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
6107 /* Redundantly setting the same lpSurface is not an error. */
6108 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6109 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
6110 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
6111 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
6112 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6113 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
6115 hr = IDirectDrawSurface3_Lock(surface3, NULL, &ddsd, 0, NULL);
6116 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
6117 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6118 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
6119 hr = IDirectDrawSurface3_Unlock(surface3, NULL);
6120 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
6122 reset_ddsd(&ddsd);
6123 ddsd.dwFlags = DDSD_LPSURFACE;
6124 ddsd.lpSurface = data;
6125 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 1);
6126 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6128 ddsd.lpSurface = NULL;
6129 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6130 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6132 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, NULL, 0);
6133 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6135 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
6136 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
6137 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6138 "Got unexpected caps %#lx.\n", ddsd.ddsCaps.dwCaps);
6140 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
6141 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6142 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6144 ddsd.dwFlags = DDSD_CAPS;
6145 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6146 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6148 /* dwCaps = 0 is allowed, but ignored. */
6149 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
6150 ddsd.lpSurface = data;
6151 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6152 ok(hr == DDERR_INVALIDCAPS, "Got hr %#lx.\n", hr);
6153 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6154 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6155 ok(hr == DDERR_INVALIDCAPS, "Got hr %#lx.\n", hr);
6156 ddsd.ddsCaps.dwCaps = 0;
6157 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6158 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
6160 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
6161 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
6162 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6163 "Got unexpected caps %#lx.\n", ddsd.ddsCaps.dwCaps);
6165 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
6166 reset_ddsd(&ddsd);
6167 ddsd.dwFlags = DDSD_HEIGHT;
6168 ddsd.dwHeight = 16;
6169 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6170 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6172 ddsd.lpSurface = data;
6173 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
6174 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6175 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
6177 ddsd.dwHeight = 0;
6178 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6179 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6181 reset_ddsd(&ddsd);
6182 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
6183 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#lx.\n", hr);
6184 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %lu.\n", ddsd.dwWidth);
6185 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %lu.\n", ddsd.dwHeight);
6187 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
6188 reset_ddsd(&ddsd);
6189 ddsd.dwFlags = DDSD_PITCH;
6190 ddsd.lPitch = 8 * 4;
6191 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6192 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6194 ddsd.dwFlags = DDSD_WIDTH;
6195 ddsd.dwWidth = 16;
6196 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6197 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6199 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
6200 ddsd.lpSurface = data;
6201 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6202 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6204 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
6205 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6206 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6208 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6209 ddsd.lPitch = 16 * 4;
6210 ddsd.dwWidth = 16;
6211 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6212 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
6214 reset_ddsd(&ddsd);
6215 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
6216 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
6217 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %lu.\n", ddsd.dwWidth);
6218 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %lu.\n", ddsd.dwHeight);
6219 ok(ddsd.lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %lu.\n", ddsd.lPitch);
6221 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
6223 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
6224 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6225 ddsd.lPitch = 4 * 4;
6226 ddsd.lpSurface = data;
6227 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6228 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#lx.\n", hr);
6230 ddsd.lPitch = 4;
6231 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6232 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#lx.\n", hr);
6234 ddsd.lPitch = 16 * 4 + 1;
6235 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6236 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6238 ddsd.lPitch = 16 * 4 + 3;
6239 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6240 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6242 ddsd.lPitch = -4;
6243 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6244 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6246 ddsd.lPitch = 16 * 4;
6247 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6248 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
6250 reset_ddsd(&ddsd);
6251 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6252 ddsd.lPitch = 0;
6253 ddsd.dwWidth = 16;
6254 ddsd.lpSurface = data;
6255 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6256 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6258 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6259 ddsd.lPitch = 16 * 4;
6260 ddsd.dwWidth = 0;
6261 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6262 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6264 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
6265 ddsd.dwFlags = DDSD_PIXELFORMAT;
6266 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
6267 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
6268 ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
6269 ddsd.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
6270 ddsd.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
6271 ddsd.ddpfPixelFormat.dwBBitMask = 0x000000ff;
6272 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6273 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6275 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
6276 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6277 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
6279 /* Can't set color keys. */
6280 reset_ddsd(&ddsd);
6281 ddsd.dwFlags = DDSD_CKSRCBLT;
6282 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
6283 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
6284 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6285 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6287 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
6288 ddsd.lpSurface = data;
6289 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6290 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
6292 /* Check that other surface properties are retained. */
6294 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
6295 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x0000ff00;
6296 hr = IDirectDrawSurface3_SetColorKey(surface3, DDCKEY_SRCBLT, &ddsd.ddckCKSrcBlt);
6297 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6299 reset_ddsd(&ddsd);
6300 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LPSURFACE;
6301 ddsd.dwWidth = 8;
6302 ddsd.lPitch = 8 * 2;
6303 ddsd.dwHeight = 8;
6304 ddsd.lpSurface = data;
6305 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
6306 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
6307 ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
6308 ddsd.ddpfPixelFormat.dwRBitMask = 0xf800;
6309 ddsd.ddpfPixelFormat.dwGBitMask = 0x07e0;
6310 ddsd.ddpfPixelFormat.dwBBitMask = 0x001f;
6311 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6312 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6314 memset(&ddsd.ddckCKSrcBlt, 0xcc, sizeof(ddsd.ddckCKSrcBlt));
6315 hr = IDirectDrawSurface3_GetColorKey(surface3, DDCKEY_SRCBLT, &ddsd.ddckCKSrcBlt);
6316 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6317 ok(ddsd.ddckCKSrcBlt.dwColorSpaceLowValue == 0x00ff00ff,
6318 "Got low color key value %#lx.\n", ddsd.ddckCKSrcBlt.dwColorSpaceLowValue);
6320 IDirectDrawSurface3_Release(surface3);
6322 /* Test mipmap texture. */
6323 reset_ddsd(&ddsd);
6324 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
6325 ddsd.dwWidth = 8;
6326 ddsd.dwHeight = 8;
6327 ddsd.dwMipMapCount = 3;
6328 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6329 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
6330 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW || hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr);
6332 if (FAILED(hr))
6334 skip("Mipmaps are not supported.\n");
6336 else
6338 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
6339 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
6340 IDirectDrawSurface_Release(surface);
6342 /* Changing surface desc for mipmap fails even without changing any
6343 * parameters. */
6344 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6345 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#lx.\n", hr);
6347 reset_ddsd(&ddsd);
6348 ddsd.dwFlags = DDSD_LPSURFACE;
6349 ddsd.lpSurface = data;
6350 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6351 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#lx.\n", hr);
6352 IDirectDrawSurface3_Release(surface3);
6355 reset_ddsd(&ddsd);
6356 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
6357 ddsd.dwWidth = 8;
6358 ddsd.dwHeight = 8;
6359 ddsd.dwMipMapCount = 3;
6360 ddsd.lpSurface = data;
6361 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6363 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
6364 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW || hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr);
6366 if (hr == DD_OK)
6368 static DDSCAPS caps = {DDSCAPS_TEXTURE};
6369 IDirectDrawSurface3 *surface2;
6371 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
6372 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
6373 IDirectDrawSurface_Release(surface);
6375 hr = IDirectDrawSurface3_GetAttachedSurface(surface3, &caps, &surface2);
6376 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
6377 reset_ddsd(&ddsd);
6378 hr = IDirectDrawSurface3_GetSurfaceDesc(surface2, &ddsd);
6379 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
6380 ok(ddsd.dwWidth == 4, "Got unexpected dwWidth %lu.\n", ddsd.dwWidth);
6382 reset_ddsd(&ddsd);
6383 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
6384 ddsd.dwWidth = 16;
6385 ddsd.dwHeight = 16;
6386 ddsd.lPitch = 16 * 4;
6387 ddsd.lpSurface = data;
6388 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6389 todo_wine ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
6391 reset_ddsd(&ddsd);
6392 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
6393 ddsd.dwWidth = 8;
6394 ddsd.dwHeight = 8;
6395 ddsd.lPitch = 8 * 4;
6396 ddsd.lpSurface = data;
6397 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6398 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
6399 if (0)
6401 /* _Lock causes access violation on Windows. */
6402 reset_ddsd(&ddsd);
6403 hr = IDirectDrawSurface3_Lock(surface2, NULL, &ddsd, DDLOCK_WAIT, NULL);
6404 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
6405 IDirectDrawSurface3_Unlock(surface2, NULL);
6408 if (0)
6410 /* Causes access violation on Windows. */
6411 reset_ddsd(&ddsd);
6412 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
6413 ddsd.dwWidth = 4;
6414 ddsd.dwHeight = 4;
6415 ddsd.lPitch = 4 * 4;
6416 ddsd.lpSurface = data;
6417 hr = IDirectDrawSurface3_SetSurfaceDesc(surface2, &ddsd, 0);
6418 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
6420 IDirectDrawSurface3_Release(surface2);
6421 IDirectDrawSurface3_Release(surface3);
6424 /* Test surface created with DDSD_LPSURFACE. */
6425 reset_ddsd(&ddsd);
6426 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LPSURFACE | DDSD_PITCH;
6427 ddsd.dwWidth = 8;
6428 ddsd.dwHeight = 8;
6429 ddsd.lpSurface = data;
6430 ddsd.lPitch = 8 * 4;
6431 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6432 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
6433 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
6435 /* SetSurfaceDesc needs systemmemory surfaces.
6437 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
6438 for (i = 0; i < ARRAY_SIZE(invalid_caps_tests); i++)
6440 reset_ddsd(&ddsd);
6441 ddsd.dwFlags = DDSD_CAPS;
6442 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
6443 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6445 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6446 ddsd.dwWidth = 8;
6447 ddsd.dwHeight = 8;
6448 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
6449 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
6450 ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
6451 ddsd.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
6452 ddsd.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
6453 ddsd.ddpfPixelFormat.dwBBitMask = 0x000000ff;
6456 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
6457 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW, "Got unexpected hr %#lx.\n", hr);
6458 if (FAILED(hr))
6460 skip("Cannot create a %s surface, skipping vidmem SetSurfaceDesc test.\n",
6461 invalid_caps_tests[i].name);
6462 goto done;
6464 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
6465 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
6466 IDirectDrawSurface_Release(surface);
6468 reset_ddsd(&ddsd);
6469 ddsd.dwFlags = DDSD_LPSURFACE;
6470 ddsd.lpSurface = data;
6471 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6472 if (invalid_caps_tests[i].supported)
6474 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
6476 else
6478 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#lx.\n",
6479 invalid_caps_tests[i].name, hr);
6481 /* Check priority of error conditions. */
6482 ddsd.dwFlags = DDSD_WIDTH;
6483 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6484 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#lx.\n",
6485 invalid_caps_tests[i].name, hr);
6488 IDirectDrawSurface3_Release(surface3);
6491 done:
6492 ref = IDirectDraw2_Release(ddraw);
6493 ok(!ref, "Unexpected refcount %lu.\n", ref);
6494 DestroyWindow(window);
6497 static void test_user_memory_getdc(void)
6499 unsigned int data[16][16], x, y;
6500 IDirectDraw2 *ddraw;
6501 HWND window;
6502 HRESULT hr;
6503 DDSURFACEDESC ddsd;
6504 IDirectDrawSurface *surface;
6505 IDirectDrawSurface3 *surface3;
6506 HBITMAP bitmap;
6507 DIBSECTION dib;
6508 ULONG ref;
6509 int size;
6510 HDC dc;
6512 window = create_window();
6513 ddraw = create_ddraw();
6514 ok(!!ddraw, "Failed to create a ddraw object.\n");
6516 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6517 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6519 reset_ddsd(&ddsd);
6520 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6521 ddsd.dwWidth = 16;
6522 ddsd.dwHeight = 16;
6523 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
6524 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
6525 ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
6526 ddsd.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
6527 ddsd.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
6528 ddsd.ddpfPixelFormat.dwBBitMask = 0x000000ff;
6529 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6530 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
6531 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6533 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
6534 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#lx.\n", hr);
6535 IDirectDrawSurface_Release(surface);
6537 memset(data, 0xaa, sizeof(data));
6538 reset_ddsd(&ddsd);
6539 ddsd.dwFlags = DDSD_LPSURFACE;
6540 ddsd.lpSurface = data;
6541 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6542 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
6544 hr = IDirectDrawSurface3_GetDC(surface3, &dc);
6545 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
6546 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
6547 ok(!!bitmap, "Failed to get bitmap.\n");
6548 size = GetObjectA(bitmap, sizeof(dib), &dib);
6549 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
6550 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
6551 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
6552 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
6553 hr = IDirectDrawSurface3_ReleaseDC(surface3, dc);
6554 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
6556 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
6557 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
6559 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
6560 ddsd.lpSurface = data;
6561 ddsd.dwWidth = 4;
6562 ddsd.dwHeight = 8;
6563 ddsd.lPitch = sizeof(*data);
6564 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6565 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
6567 memset(data, 0xaa, sizeof(data));
6568 hr = IDirectDrawSurface3_GetDC(surface3, &dc);
6569 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
6570 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
6571 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
6572 hr = IDirectDrawSurface3_ReleaseDC(surface3, dc);
6573 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
6575 for (y = 0; y < 4; y++)
6577 for (x = 0; x < 4; x++)
6579 if ((x == 1 || x == 2) && (y == 1 || y == 2))
6580 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
6581 x, y, data[y][x]);
6582 else
6583 ok(data[y][x] == 0x00000000, "Expected color 0xaaaaaaaa on position %ux%u, got %#x.\n",
6584 x, y, data[y][x]);
6587 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
6588 data[0][5]);
6589 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
6590 data[7][3]);
6591 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
6592 data[7][4]);
6593 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
6594 data[8][0]);
6596 IDirectDrawSurface3_Release(surface3);
6597 ref = IDirectDraw2_Release(ddraw);
6598 ok(!ref, "Unexpected refcount %lu.\n", ref);
6599 DestroyWindow(window);
6602 static void test_sysmem_overlay(void)
6604 IDirectDraw2 *ddraw;
6605 HWND window;
6606 HRESULT hr;
6607 DDSURFACEDESC ddsd;
6608 IDirectDrawSurface *surface;
6609 ULONG ref;
6611 window = create_window();
6612 ddraw = create_ddraw();
6613 ok(!!ddraw, "Failed to create a ddraw object.\n");
6615 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6616 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6618 reset_ddsd(&ddsd);
6619 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
6620 ddsd.dwWidth = 16;
6621 ddsd.dwHeight = 16;
6622 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
6623 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
6624 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
6625 ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
6626 ddsd.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
6627 ddsd.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
6628 ddsd.ddpfPixelFormat.dwBBitMask = 0x000000ff;
6629 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
6630 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#lx.\n", hr);
6632 ref = IDirectDraw2_Release(ddraw);
6633 ok(!ref, "Unexpected refcount %lu.\n", ref);
6634 DestroyWindow(window);
6637 static void test_primary_palette(void)
6639 DDSCAPS surface_caps = {DDSCAPS_FLIP};
6640 IDirectDrawSurface *primary, *backbuffer;
6641 PALETTEENTRY palette_entries[256];
6642 IDirectDrawPalette *palette, *tmp;
6643 DDSURFACEDESC surface_desc;
6644 IDirectDraw2 *ddraw;
6645 DWORD palette_caps;
6646 ULONG refcount;
6647 HWND window;
6648 HRESULT hr;
6650 window = create_window();
6651 ddraw = create_ddraw();
6652 ok(!!ddraw, "Failed to create a ddraw object.\n");
6653 if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
6655 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
6656 IDirectDraw2_Release(ddraw);
6657 DestroyWindow(window);
6658 return;
6660 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6661 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6663 memset(&surface_desc, 0, sizeof(surface_desc));
6664 surface_desc.dwSize = sizeof(surface_desc);
6665 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6666 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6667 surface_desc.dwBackBufferCount = 1;
6668 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
6669 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6670 hr = IDirectDrawSurface_GetAttachedSurface(primary, &surface_caps, &backbuffer);
6671 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#lx.\n", hr);
6673 memset(palette_entries, 0, sizeof(palette_entries));
6674 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
6675 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
6676 refcount = get_refcount((IUnknown *)palette);
6677 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
6679 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6680 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#lx.\n", hr);
6681 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#lx.\n", palette_caps);
6683 hr = IDirectDrawSurface_SetPalette(primary, palette);
6684 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
6686 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
6687 * and is generally somewhat broken with respect to 8 bpp / palette
6688 * handling. */
6689 if (SUCCEEDED(IDirectDrawSurface_GetPalette(backbuffer, &tmp)))
6691 win_skip("Broken palette handling detected, skipping tests.\n");
6692 IDirectDrawPalette_Release(tmp);
6693 IDirectDrawPalette_Release(palette);
6694 /* The Windows 8 testbot keeps extra references to the primary and
6695 * backbuffer while in 8 bpp mode. */
6696 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
6697 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#lx.\n", hr);
6698 goto done;
6701 refcount = get_refcount((IUnknown *)palette);
6702 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
6704 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6705 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#lx.\n", hr);
6706 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
6707 "Got unexpected palette caps %#lx.\n", palette_caps);
6709 hr = IDirectDrawSurface_SetPalette(primary, NULL);
6710 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
6711 refcount = get_refcount((IUnknown *)palette);
6712 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
6714 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6715 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#lx.\n", hr);
6716 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#lx.\n", palette_caps);
6718 hr = IDirectDrawSurface_SetPalette(primary, palette);
6719 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
6720 refcount = get_refcount((IUnknown *)palette);
6721 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
6723 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
6724 ok(SUCCEEDED(hr), "Failed to get palette, hr %#lx.\n", hr);
6725 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
6726 IDirectDrawPalette_Release(tmp);
6727 hr = IDirectDrawSurface_GetPalette(backbuffer, &tmp);
6728 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#lx.\n", hr);
6730 refcount = IDirectDrawPalette_Release(palette);
6731 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
6732 refcount = IDirectDrawPalette_Release(palette);
6733 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
6735 /* Note that this only seems to work when the palette is attached to the
6736 * primary surface. When attached to a regular surface, attempting to get
6737 * the palette here will cause an access violation. */
6738 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
6739 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#lx.\n", hr);
6741 hr = IDirectDrawSurface_IsLost(primary);
6742 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
6744 memset(&surface_desc, 0, sizeof(surface_desc));
6745 surface_desc.dwSize = sizeof(surface_desc);
6746 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
6747 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
6748 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %lu.\n", surface_desc.dwWidth);
6749 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %lu.\n", surface_desc.dwHeight);
6750 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == 8, "Got unexpected bit count %lu.\n",
6751 surface_desc.ddpfPixelFormat.dwRGBBitCount);
6753 hr = set_display_mode(ddraw, 640, 480);
6754 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
6756 memset(&surface_desc, 0, sizeof(surface_desc));
6757 surface_desc.dwSize = sizeof(surface_desc);
6758 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
6759 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
6760 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %lu.\n", surface_desc.dwWidth);
6761 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %lu.\n", surface_desc.dwHeight);
6762 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == 32
6763 || surface_desc.ddpfPixelFormat.dwRGBBitCount == 24,
6764 "Got unexpected bit count %lu.\n", surface_desc.ddpfPixelFormat.dwRGBBitCount);
6766 hr = IDirectDrawSurface_IsLost(primary);
6767 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
6768 hr = IDirectDrawSurface_Restore(primary);
6769 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
6770 hr = IDirectDrawSurface_IsLost(primary);
6771 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
6773 memset(&surface_desc, 0, sizeof(surface_desc));
6774 surface_desc.dwSize = sizeof(surface_desc);
6775 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
6776 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
6777 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %lu.\n", surface_desc.dwWidth);
6778 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %lu.\n", surface_desc.dwHeight);
6779 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == 32
6780 || surface_desc.ddpfPixelFormat.dwRGBBitCount == 24,
6781 "Got unexpected bit count %lu.\n", surface_desc.ddpfPixelFormat.dwRGBBitCount);
6783 done:
6784 refcount = IDirectDrawSurface_Release(backbuffer);
6785 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
6786 refcount = IDirectDrawSurface_Release(primary);
6787 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
6788 refcount = IDirectDraw2_Release(ddraw);
6789 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
6790 DestroyWindow(window);
6793 static HRESULT WINAPI surface_counter(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
6795 UINT *surface_count = context;
6797 ++(*surface_count);
6798 IDirectDrawSurface_Release(surface);
6800 return DDENUMRET_OK;
6803 static void test_surface_attachment(void)
6805 IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
6806 DDSCAPS caps = {DDSCAPS_TEXTURE};
6807 DDSURFACEDESC surface_desc;
6808 IDirectDraw2 *ddraw;
6809 UINT surface_count;
6810 ULONG refcount;
6811 HWND window;
6812 HRESULT hr;
6814 window = create_window();
6815 ddraw = create_ddraw();
6816 ok(!!ddraw, "Failed to create a ddraw object.\n");
6817 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6818 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6820 memset(&surface_desc, 0, sizeof(surface_desc));
6821 surface_desc.dwSize = sizeof(surface_desc);
6822 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
6823 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6824 surface_desc.dwMipMapCount = 3;
6825 surface_desc.dwWidth = 128;
6826 surface_desc.dwHeight = 128;
6827 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6828 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6830 hr = IDirectDrawSurface_GetAttachedSurface(surface1, &caps, &surface2);
6831 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#lx.\n", hr);
6832 hr = IDirectDrawSurface_GetAttachedSurface(surface2, &caps, &surface3);
6833 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#lx.\n", hr);
6834 hr = IDirectDrawSurface_GetAttachedSurface(surface3, &caps, &surface4);
6835 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
6837 surface_count = 0;
6838 IDirectDrawSurface_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
6839 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6840 surface_count = 0;
6841 IDirectDrawSurface_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
6842 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6843 surface_count = 0;
6844 IDirectDrawSurface_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
6845 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
6847 memset(&surface_desc, 0, sizeof(surface_desc));
6848 surface_desc.dwSize = sizeof(surface_desc);
6849 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6850 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6851 surface_desc.dwWidth = 16;
6852 surface_desc.dwHeight = 16;
6853 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6854 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6856 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
6857 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
6858 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
6859 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
6860 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
6861 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
6862 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
6863 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
6864 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
6865 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
6866 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
6867 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
6869 IDirectDrawSurface_Release(surface4);
6871 memset(&surface_desc, 0, sizeof(surface_desc));
6872 surface_desc.dwSize = sizeof(surface_desc);
6873 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6874 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6875 surface_desc.dwWidth = 16;
6876 surface_desc.dwHeight = 16;
6877 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6878 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6880 if (SUCCEEDED(hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4)))
6882 skip("Running on refrast, skipping some tests.\n");
6883 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface4);
6884 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
6886 else
6888 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
6889 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
6890 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
6891 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
6892 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
6893 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
6894 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
6895 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
6896 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
6897 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
6898 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
6901 IDirectDrawSurface_Release(surface4);
6902 IDirectDrawSurface_Release(surface3);
6903 IDirectDrawSurface_Release(surface2);
6904 IDirectDrawSurface_Release(surface1);
6906 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6907 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6909 /* Try a single primary and two offscreen plain surfaces. */
6910 memset(&surface_desc, 0, sizeof(surface_desc));
6911 surface_desc.dwSize = sizeof(surface_desc);
6912 surface_desc.dwFlags = DDSD_CAPS;
6913 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
6914 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6915 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6917 memset(&surface_desc, 0, sizeof(surface_desc));
6918 surface_desc.dwSize = sizeof(surface_desc);
6919 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6920 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6921 surface_desc.dwWidth = registry_mode.dmPelsWidth;
6922 surface_desc.dwHeight = registry_mode.dmPelsHeight;
6923 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
6924 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6926 memset(&surface_desc, 0, sizeof(surface_desc));
6927 surface_desc.dwSize = sizeof(surface_desc);
6928 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6929 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6930 surface_desc.dwWidth = registry_mode.dmPelsWidth;
6931 surface_desc.dwHeight = registry_mode.dmPelsHeight;
6932 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
6933 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6935 /* This one has a different size. */
6936 memset(&surface_desc, 0, sizeof(surface_desc));
6937 surface_desc.dwSize = sizeof(surface_desc);
6938 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6939 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6940 surface_desc.dwWidth = 128;
6941 surface_desc.dwHeight = 128;
6942 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6943 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6945 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
6946 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
6947 /* Try the reverse without detaching first. */
6948 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
6949 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#lx.\n", hr);
6950 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
6951 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
6953 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
6954 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
6955 /* Try to detach reversed. */
6956 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
6957 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#lx.\n", hr);
6958 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
6959 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
6961 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
6962 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
6963 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
6964 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
6966 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
6967 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
6968 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
6969 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
6971 IDirectDrawSurface_Release(surface4);
6972 IDirectDrawSurface_Release(surface3);
6973 IDirectDrawSurface_Release(surface2);
6974 IDirectDrawSurface_Release(surface1);
6976 /* Test depth surfaces of different sizes. */
6977 memset(&surface_desc, 0, sizeof(surface_desc));
6978 surface_desc.dwSize = sizeof(surface_desc);
6979 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6980 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6981 surface_desc.dwWidth = 64;
6982 surface_desc.dwHeight = 64;
6983 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6984 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
6986 memset(&surface_desc, 0, sizeof(surface_desc));
6987 surface_desc.dwSize = sizeof(surface_desc);
6988 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
6989 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
6990 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6991 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
6992 surface_desc.ddpfPixelFormat.dwZBufferBitDepth = 16;
6993 surface_desc.ddpfPixelFormat.dwZBitMask = 0x0000ffff;
6994 surface_desc.dwWidth = 32;
6995 surface_desc.dwHeight = 32;
6996 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
6997 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
6998 surface_desc.dwWidth = 64;
6999 surface_desc.dwHeight = 64;
7000 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7001 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
7002 surface_desc.dwWidth = 128;
7003 surface_desc.dwHeight = 128;
7004 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7005 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
7007 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
7008 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
7009 if (SUCCEEDED(hr))
7010 IDirectDrawSurface2_DeleteAttachedSurface(surface1, 0, surface2);
7011 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface3);
7012 ok(hr == D3D_OK, "Failed to attach depth buffer, hr %#lx.\n", hr);
7013 hr = IDirectDrawSurface2_DeleteAttachedSurface(surface1, 0, surface3);
7014 ok(hr == D3D_OK, "Failed to detach depth buffer, hr %#lx.\n", hr);
7015 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
7016 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
7018 IDirectDrawSurface2_Release(surface4);
7019 IDirectDrawSurface2_Release(surface3);
7020 IDirectDrawSurface2_Release(surface2);
7021 IDirectDrawSurface2_Release(surface1);
7023 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
7024 memset(&surface_desc, 0, sizeof(surface_desc));
7025 surface_desc.dwSize = sizeof(surface_desc);
7026 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7027 surface_desc.dwWidth = 64;
7028 surface_desc.dwHeight = 64;
7029 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
7030 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7031 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
7032 surface_desc.ddpfPixelFormat.dwRGBBitCount = 16;
7033 surface_desc.ddpfPixelFormat.dwRBitMask = 0xf800;
7034 surface_desc.ddpfPixelFormat.dwGBitMask = 0x07e0;
7035 surface_desc.ddpfPixelFormat.dwBBitMask = 0x001f;
7036 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7037 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
7038 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7039 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
7041 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7042 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
7043 surface_desc.ddpfPixelFormat.dwZBufferBitDepth = 16;
7044 surface_desc.ddpfPixelFormat.dwZBitMask = 0x0000ffff;
7045 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7046 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
7048 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
7049 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
7050 refcount = get_refcount((IUnknown *)surface2);
7051 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
7052 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
7053 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#lx.\n", hr);
7055 /* Attaching while already attached to other surface. */
7056 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
7057 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
7058 hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
7059 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
7060 IDirectDrawSurface_Release(surface3);
7062 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
7063 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
7064 refcount = get_refcount((IUnknown *)surface2);
7065 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
7067 /* Automatic detachment on release. */
7068 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
7069 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
7070 refcount = get_refcount((IUnknown *)surface2);
7071 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
7072 refcount = IDirectDrawSurface_Release(surface1);
7073 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7074 refcount = IDirectDrawSurface_Release(surface2);
7075 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7076 refcount = IDirectDraw2_Release(ddraw);
7077 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7078 DestroyWindow(window);
7081 static void test_pixel_format(void)
7083 HWND window, window2, window3;
7084 HMODULE gl = NULL;
7085 int format, test_format;
7086 PIXELFORMATDESCRIPTOR pfd;
7087 IDirectDraw2 *ddraw = NULL;
7088 IDirectDrawClipper *clipper = NULL;
7089 HDC hdc, hdc2, hdc3;
7090 DDSURFACEDESC ddsd;
7091 IDirectDrawSurface *primary = NULL, *offscreen;
7092 ULONG refcount;
7093 DDBLTFX fx;
7094 HRESULT hr;
7095 BOOL ret;
7097 window = create_window();
7098 ok(!!window, "Failed to create window.\n");
7099 window2 = create_window();
7100 ok(!!window2, "Failed to create window.\n");
7102 hdc = GetDC(window);
7103 ok(!!hdc, "Failed to get DC.\n");
7104 hdc2 = GetDC(window2);
7105 ok(!!hdc2, "Failed to get DC.\n");
7107 gl = LoadLibraryA("opengl32.dll");
7108 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
7110 format = GetPixelFormat(hdc);
7111 ok(format == 0, "new window has pixel format %d\n", format);
7113 ZeroMemory(&pfd, sizeof(pfd));
7114 pfd.nSize = sizeof(pfd);
7115 pfd.nVersion = 1;
7116 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
7117 pfd.iPixelType = PFD_TYPE_RGBA;
7118 pfd.iLayerType = PFD_MAIN_PLANE;
7119 format = ChoosePixelFormat(hdc, &pfd);
7120 if (format <= 0)
7122 skip("no pixel format available\n");
7123 goto cleanup;
7126 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
7128 skip("failed to set pixel format\n");
7129 goto cleanup;
7132 if (!SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
7134 skip("failed to set pixel format on second window\n");
7135 goto cleanup;
7138 ddraw = create_ddraw();
7139 ok(!!ddraw, "Failed to create a ddraw object.\n");
7141 test_format = GetPixelFormat(hdc);
7142 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7144 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7145 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7147 test_format = GetPixelFormat(hdc);
7148 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7150 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
7151 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
7152 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
7153 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
7155 test_format = GetPixelFormat(hdc);
7156 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7157 test_format = GetPixelFormat(hdc2);
7158 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7160 memset(&ddsd, 0, sizeof(ddsd));
7161 ddsd.dwSize = sizeof(ddsd);
7162 ddsd.dwFlags = DDSD_CAPS;
7163 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7165 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
7166 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
7168 test_format = GetPixelFormat(hdc);
7169 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7170 test_format = GetPixelFormat(hdc2);
7171 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7173 hr = IDirectDrawSurface_SetClipper(primary, clipper);
7174 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
7176 test_format = GetPixelFormat(hdc);
7177 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7178 test_format = GetPixelFormat(hdc2);
7179 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7181 memset(&ddsd, 0, sizeof(ddsd));
7182 ddsd.dwSize = sizeof(ddsd);
7183 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7184 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7185 ddsd.dwWidth = ddsd.dwHeight = 64;
7186 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &offscreen, NULL);
7187 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
7189 memset(&fx, 0, sizeof(fx));
7190 fx.dwSize = sizeof(fx);
7191 hr = IDirectDrawSurface_Blt(offscreen, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
7192 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#lx.\n", hr);
7194 test_format = GetPixelFormat(hdc);
7195 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7197 hr = IDirectDrawSurface_Blt(primary, NULL, offscreen, NULL, DDBLT_WAIT, NULL);
7198 ok(SUCCEEDED(hr), "Failed to blit to primary surface, hr %#lx.\n", hr);
7200 test_format = GetPixelFormat(hdc);
7201 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7202 test_format = GetPixelFormat(hdc2);
7203 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7205 IDirectDrawSurface_Release(offscreen);
7206 IDirectDrawSurface_Release(primary);
7207 refcount = IDirectDrawClipper_Release(clipper);
7208 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7209 refcount = IDirectDraw2_Release(ddraw);
7210 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7212 /* Test that creating a device doesn't set a pixel format on a window which
7213 * never had one. */
7215 window3 = create_window();
7216 hdc3 = GetDC(window3);
7218 test_format = GetPixelFormat(hdc3);
7219 ok(!test_format, "Expected no format, got %d.\n", test_format);
7221 ddraw = create_ddraw();
7222 ok(!!ddraw, "Failed to create a ddraw object.\n");
7223 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window3, DDSCL_NORMAL);
7224 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7226 test_format = GetPixelFormat(hdc3);
7227 ok(!test_format, "Expected no format, got %d.\n", test_format);
7229 memset(&ddsd, 0, sizeof(ddsd));
7230 ddsd.dwSize = sizeof(ddsd);
7231 ddsd.dwFlags = DDSD_CAPS;
7232 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7233 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
7234 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7236 memset(&ddsd, 0, sizeof(ddsd));
7237 ddsd.dwSize = sizeof(ddsd);
7238 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7239 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7240 ddsd.dwWidth = ddsd.dwHeight = 64;
7241 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &offscreen, NULL);
7242 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
7244 memset(&fx, 0, sizeof(fx));
7245 fx.dwSize = sizeof(fx);
7246 hr = IDirectDrawSurface_Blt(offscreen, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
7247 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#lx.\n", hr);
7249 hr = IDirectDrawSurface_Blt(primary, NULL, offscreen, NULL, DDBLT_WAIT, NULL);
7250 ok(SUCCEEDED(hr), "Failed to blit to primary surface, hr %#lx.\n", hr);
7252 test_format = GetPixelFormat(hdc3);
7253 ok(!test_format, "Expected no format, got %d.\n", test_format);
7255 IDirectDrawSurface_Release(offscreen);
7256 IDirectDrawSurface_Release(primary);
7257 refcount = IDirectDraw2_Release(ddraw);
7258 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7260 test_format = GetPixelFormat(hdc3);
7261 ok(!test_format, "Expected no format, got %d.\n", test_format);
7263 ret = SetPixelFormat(hdc3, format, &pfd);
7264 ok(ret, "Failed to set pixel format %d.\n", format);
7266 test_format = GetPixelFormat(hdc3);
7267 ok(test_format == format, "Expected pixel format %d, got %d.\n", format, test_format);
7269 ReleaseDC(window3, hdc3);
7270 DestroyWindow(window3);
7272 cleanup:
7273 FreeLibrary(gl);
7274 ReleaseDC(window2, hdc2);
7275 ReleaseDC(window, hdc);
7276 DestroyWindow(window2);
7277 DestroyWindow(window);
7280 static void test_create_surface_pitch(void)
7282 DWORD vidmem_total = 0, vidmem_free = 0, vidmem_free2 = 0;
7283 DDSCAPS vidmem_caps = {DDSCAPS_TEXTURE};
7284 IDirectDrawSurface * surface, *primary;
7285 DDSURFACEDESC surface_desc;
7286 IDirectDraw2 *ddraw;
7287 unsigned int i;
7288 ULONG refcount;
7289 HWND window;
7290 HRESULT hr;
7291 void *mem;
7293 static const struct
7295 DWORD caps;
7296 DWORD flags_in;
7297 DWORD pitch_in;
7298 HRESULT hr;
7299 DWORD flags_out;
7300 DWORD pitch_out32;
7301 DWORD pitch_out64;
7303 test_data[] =
7305 /* 0 */
7306 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7307 0, 0, DD_OK,
7308 DDSD_PITCH, 0x100, 0x100},
7309 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7310 DDSD_PITCH, 0x104, DD_OK,
7311 DDSD_PITCH, 0x100, 0x100},
7312 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7313 DDSD_PITCH, 0x0f8, DD_OK,
7314 DDSD_PITCH, 0x100, 0x100},
7315 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7316 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7317 0, 0, 0 },
7318 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7319 0, 0, DD_OK,
7320 DDSD_PITCH, 0x100, 0x0fc},
7321 /* 5 */
7322 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7323 DDSD_PITCH, 0x104, DD_OK,
7324 DDSD_PITCH, 0x100, 0x0fc},
7325 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7326 DDSD_PITCH, 0x0f8, DD_OK,
7327 DDSD_PITCH, 0x100, 0x0fc},
7328 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7329 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
7330 DDSD_PITCH, 0x100, 0x0fc},
7331 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7332 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
7333 0, 0, 0 },
7334 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7335 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
7336 0, 0, 0 },
7337 /* 10 */
7338 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7339 0, 0, DDERR_INVALIDCAPS,
7340 0, 0, 0 },
7341 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7342 0, 0, DD_OK,
7343 DDSD_PITCH, 0x100, 0 },
7344 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE,
7345 0, 0, DD_OK,
7346 DDSD_PITCH, 0x100, 0 },
7347 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7348 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7349 0, 0, 0 },
7350 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7351 0, 0, DDERR_INVALIDCAPS,
7352 0, 0, 0 },
7353 /* 15 */
7354 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7355 0, 0, DD_OK,
7356 DDSD_PITCH, 0x100, 0 },
7357 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7358 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
7359 0, 0, 0 },
7360 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
7361 0, 0, DD_OK,
7362 DDSD_PITCH, 0x100, 0x0fc},
7363 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
7364 0, 0, DD_OK,
7365 DDSD_PITCH, 0x100, 0x100},
7367 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
7369 window = create_window();
7370 ddraw = create_ddraw();
7371 ok(!!ddraw, "Failed to create a ddraw object.\n");
7372 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
7373 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
7375 mem = calloc((63 * 4) + 8, 63);
7377 /* We need a primary surface and exclusive mode for video memory accounting to work
7378 * right on Windows. Otherwise it gives us junk data, like creating a video memory
7379 * surface freeing up memory. */
7380 memset(&surface_desc, 0, sizeof(surface_desc));
7381 surface_desc.dwSize = sizeof(surface_desc);
7382 surface_desc.dwFlags = DDSD_CAPS;
7383 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7384 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
7385 ok(SUCCEEDED(hr), "Failed to create a primary surface, hr %#lx.\n", hr);
7387 hr = IDirectDraw2_GetAvailableVidMem(ddraw, &vidmem_caps, &vidmem_total, &vidmem_free);
7388 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW,
7389 "Failed to get available video memory, hr %#lx.\n", hr);
7391 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7393 memset(&surface_desc, 0, sizeof(surface_desc));
7394 surface_desc.dwSize = sizeof(surface_desc);
7395 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
7396 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
7397 surface_desc.dwWidth = 63;
7398 surface_desc.dwHeight = 63;
7399 surface_desc.lPitch = test_data[i].pitch_in;
7400 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7401 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
7402 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
7403 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
7404 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
7405 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
7406 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7407 if (test_data[i].flags_in & DDSD_LPSURFACE)
7409 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
7410 ok(hr == expected_hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n", i, hr, expected_hr);
7411 surface_desc.lpSurface = mem;
7412 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7414 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
7415 continue;
7416 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n", i, hr, test_data[i].hr);
7417 if (FAILED(hr))
7418 continue;
7420 memset(&surface_desc, 0, sizeof(surface_desc));
7421 surface_desc.dwSize = sizeof(surface_desc);
7422 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
7423 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#lx.\n", i, hr);
7424 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
7425 "Test %u: Got unexpected flags %#lx, expected %#lx.\n",
7426 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
7427 /* The pitch for textures seems to be implementation specific. */
7428 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
7430 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
7431 todo_wine ok(surface_desc.lPitch == test_data[i].pitch_out64,
7432 "Test %u: Got unexpected pitch %#lx, expected %#lx.\n",
7433 i, surface_desc.lPitch, test_data[i].pitch_out64);
7434 else
7435 ok(surface_desc.lPitch == test_data[i].pitch_out32,
7436 "Test %u: Got unexpected pitch %#lx, expected %#lx.\n",
7437 i, surface_desc.lPitch, test_data[i].pitch_out32);
7439 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
7441 hr = IDirectDraw2_GetAvailableVidMem(ddraw, &vidmem_caps, &vidmem_total, &vidmem_free2);
7442 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW,
7443 "Failed to get available video memory, hr %#lx.\n", hr);
7444 if (SUCCEEDED(hr) && surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
7446 /* Star Trek Starfleet Academy cares about this bit here: That creating a system memory
7447 * resource does not influence available video memory. */
7448 ok(vidmem_free2 == vidmem_free, "Free video memory changed from %#lx to %#lx, test %u.\n",
7449 vidmem_free, vidmem_free2, i);
7451 else if (SUCCEEDED(hr) && surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
7453 /* DDSCAPS_ALLOCONLOAD does not seem to delay video memory allocation, at least not on
7454 * modern Windows.
7456 * The amount of video memory consumed is different from what dwHeight * lPitch would
7457 * suggest, although not by much. */
7458 ok(vidmem_free2 < vidmem_free,
7459 "Expected free video memory to change, but it did not, test %u.\n", i);
7462 IDirectDrawSurface_Release(surface);
7464 hr = IDirectDraw2_GetAvailableVidMem(ddraw, &vidmem_caps, &vidmem_total, &vidmem_free2);
7465 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW,
7466 "Failed to get available video memory, hr %#lx.\n", hr);
7467 ok(hr == DDERR_NODIRECTDRAWHW || vidmem_free2 == vidmem_free,
7468 "Free video memory changed from %#lx to %#lx, test %u.\n",
7469 vidmem_free, vidmem_free2, i);
7472 IDirectDrawSurface_Release(primary);
7473 free(mem);
7474 refcount = IDirectDraw2_Release(ddraw);
7475 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7476 DestroyWindow(window);
7479 static void test_mipmap(void)
7481 IDirectDrawSurface *surface1;
7482 IDirectDrawSurface2 *surface, *surface_base, *surface_mip;
7483 unsigned int i, mipmap_count;
7484 DDSURFACEDESC surface_desc;
7485 IDirectDraw2 *ddraw;
7486 ULONG refcount;
7487 HWND window;
7488 HRESULT hr;
7489 DDSCAPS caps = {DDSCAPS_COMPLEX};
7490 DDCAPS hal_caps;
7492 static const struct
7494 DWORD flags;
7495 DWORD caps;
7496 DWORD width;
7497 DWORD height;
7498 DWORD mipmap_count_in;
7499 HRESULT hr;
7500 DWORD mipmap_count_out;
7502 tests[] =
7504 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS},
7505 {0, DDSCAPS_COMPLEX, 128, 32, 0, DDERR_INVALIDCAPS},
7506 {0, DDSCAPS_MIPMAP | DDSCAPS_COMPLEX, 128, 32, 0, DDERR_INVALIDCAPS},
7507 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
7508 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX, 128, 32, 0, DDERR_INVALIDCAPS},
7509 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 6},
7510 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 6},
7512 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 1, DDERR_INVALIDCAPS},
7513 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 3, DDERR_INVALIDCAPS},
7514 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
7515 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS},
7518 window = create_window();
7519 ddraw = create_ddraw();
7520 ok(!!ddraw, "Failed to create a ddraw object.\n");
7521 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7522 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
7524 memset(&hal_caps, 0, sizeof(hal_caps));
7525 hal_caps.dwSize = sizeof(hal_caps);
7526 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
7527 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
7528 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7530 skip("Mipmapped textures not supported, skipping tests.\n");
7531 IDirectDraw2_Release(ddraw);
7532 DestroyWindow(window);
7533 return;
7536 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7538 memset(&surface_desc, 0, sizeof(surface_desc));
7539 surface_desc.dwSize = sizeof(surface_desc);
7540 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
7541 surface_desc.ddsCaps.dwCaps = tests[i].caps;
7542 surface_desc.dwWidth = tests[i].width;
7543 surface_desc.dwHeight = tests[i].height;
7544 if (tests[i].flags & DDSD_MIPMAPCOUNT)
7545 surface_desc.dwMipMapCount = tests[i].mipmap_count_in;
7546 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7547 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#lx.\n", i, hr);
7548 if (FAILED(hr))
7549 continue;
7551 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
7552 ok(SUCCEEDED(hr), "Test %u: Failed to get IDirectDrawSurface2 interface, hr %#lx.\n", i, hr);
7553 IDirectDrawSurface_Release(surface1);
7555 memset(&surface_desc, 0, sizeof(surface_desc));
7556 surface_desc.dwSize = sizeof(surface_desc);
7557 hr = IDirectDrawSurface2_GetSurfaceDesc(surface, &surface_desc);
7558 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#lx.\n", i, hr);
7559 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
7560 "Test %u: Got unexpected flags %#lx.\n", i, surface_desc.dwFlags);
7561 ok(surface_desc.dwMipMapCount == tests[i].mipmap_count_out,
7562 "Test %u: Got unexpected mipmap count %lu.\n", i, surface_desc.dwMipMapCount);
7564 surface_base = surface;
7565 IDirectDrawSurface2_AddRef(surface_base);
7566 mipmap_count = surface_desc.dwMipMapCount;
7567 while (mipmap_count > 1)
7569 hr = IDirectDrawSurface2_GetAttachedSurface(surface_base, &caps, &surface_mip);
7570 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get attached surface, hr %#lx.\n", i, mipmap_count, hr);
7572 memset(&surface_desc, 0, sizeof(surface_desc));
7573 surface_desc.dwSize = sizeof(surface_desc);
7574 hr = IDirectDrawSurface2_GetSurfaceDesc(surface_base, &surface_desc);
7575 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get surface desc, hr %#lx.\n", i, mipmap_count, hr);
7576 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
7577 "Test %u, %u: Got unexpected flags %#lx.\n", i, mipmap_count, surface_desc.dwFlags);
7578 ok(surface_desc.dwMipMapCount == mipmap_count,
7579 "Test %u, %u: Got unexpected mipmap count %lu.\n",
7580 i, mipmap_count, surface_desc.dwMipMapCount);
7582 memset(&surface_desc, 0, sizeof(surface_desc));
7583 surface_desc.dwSize = sizeof(surface_desc);
7584 hr = IDirectDrawSurface2_Lock(surface_base, NULL, &surface_desc, 0, NULL);
7585 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#lx.\n", i, mipmap_count, hr);
7586 ok(surface_desc.dwMipMapCount == mipmap_count,
7587 "Test %u, %u: unexpected change of mipmap count %lu.\n",
7588 i, mipmap_count, surface_desc.dwMipMapCount);
7589 memset(&surface_desc, 0, sizeof(surface_desc));
7590 surface_desc.dwSize = sizeof(surface_desc);
7591 hr = IDirectDrawSurface2_Lock(surface_mip, NULL, &surface_desc, 0, NULL);
7592 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#lx.\n", i, mipmap_count, hr);
7593 ok(surface_desc.dwMipMapCount == mipmap_count - 1,
7594 "Test %u, %u: Got unexpected child mipmap count %lu.\n", i, mipmap_count, surface_desc.dwMipMapCount);
7595 IDirectDrawSurface2_Unlock(surface_mip, NULL);
7596 IDirectDrawSurface2_Unlock(surface_base, NULL);
7598 IDirectDrawSurface2_Release(surface_base);
7599 surface_base = surface_mip;
7600 --mipmap_count;
7602 IDirectDrawSurface2_Release(surface_base);
7604 IDirectDrawSurface2_Release(surface);
7607 refcount = IDirectDraw2_Release(ddraw);
7608 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7609 DestroyWindow(window);
7612 static void test_palette_complex(void)
7614 IDirectDrawSurface *surface1;
7615 IDirectDrawSurface2 *surface, *mipmap, *tmp;
7616 DDSURFACEDESC surface_desc;
7617 IDirectDraw2 *ddraw;
7618 IDirectDrawPalette *palette, *palette2, *palette_mipmap;
7619 ULONG refcount;
7620 HWND window;
7621 HRESULT hr;
7622 DDSCAPS caps = {DDSCAPS_COMPLEX};
7623 DDCAPS hal_caps;
7624 PALETTEENTRY palette_entries[256];
7625 unsigned int i;
7626 HDC dc;
7627 RGBQUAD rgbquad;
7628 UINT count;
7630 window = create_window();
7631 ddraw = create_ddraw();
7632 ok(!!ddraw, "Failed to create a ddraw object.\n");
7633 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7634 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
7636 memset(&hal_caps, 0, sizeof(hal_caps));
7637 hal_caps.dwSize = sizeof(hal_caps);
7638 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
7639 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
7640 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7642 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
7643 IDirectDraw2_Release(ddraw);
7644 DestroyWindow(window);
7645 return;
7648 memset(&surface_desc, 0, sizeof(surface_desc));
7649 surface_desc.dwSize = sizeof(surface_desc);
7650 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7651 surface_desc.dwWidth = 128;
7652 surface_desc.dwHeight = 128;
7653 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7654 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7655 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7656 surface_desc.ddpfPixelFormat.dwRGBBitCount = 8;
7657 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7658 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
7659 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
7660 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#lx.\n", hr);
7661 IDirectDrawSurface_Release(surface1);
7663 memset(palette_entries, 0, sizeof(palette_entries));
7664 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7665 palette_entries, &palette, NULL);
7666 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
7668 memset(palette_entries, 0, sizeof(palette_entries));
7669 palette_entries[1].peRed = 0xff;
7670 palette_entries[1].peGreen = 0x80;
7671 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7672 palette_entries, &palette_mipmap, NULL);
7673 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
7675 palette2 = (void *)0xdeadbeef;
7676 hr = IDirectDrawSurface2_GetPalette(surface, &palette2);
7677 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#lx.\n", hr);
7678 ok(!palette2, "Got unexpected palette %p.\n", palette2);
7679 hr = IDirectDrawSurface2_SetPalette(surface, palette);
7680 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
7681 hr = IDirectDrawSurface2_GetPalette(surface, &palette2);
7682 ok(SUCCEEDED(hr), "Failed to get palette, hr %#lx.\n", hr);
7683 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
7684 IDirectDrawPalette_Release(palette2);
7686 mipmap = surface;
7687 IDirectDrawSurface2_AddRef(mipmap);
7688 for (i = 0; i < 7; ++i)
7690 hr = IDirectDrawSurface2_GetAttachedSurface(mipmap, &caps, &tmp);
7691 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#lx.\n", i, hr);
7692 palette2 = (void *)0xdeadbeef;
7693 hr = IDirectDrawSurface2_GetPalette(tmp, &palette2);
7694 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#lx, i %u.\n", hr, i);
7695 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
7697 hr = IDirectDrawSurface2_SetPalette(tmp, palette_mipmap);
7698 ok(SUCCEEDED(hr), "Failed to set palette, i %u, hr %#lx.\n", i, hr);
7700 hr = IDirectDrawSurface2_GetPalette(tmp, &palette2);
7701 ok(SUCCEEDED(hr), "Failed to get palette, i %u, hr %#lx.\n", i, hr);
7702 ok(palette_mipmap == palette2, "Got unexpected palette %p.\n", palette2);
7703 IDirectDrawPalette_Release(palette2);
7705 hr = IDirectDrawSurface2_GetDC(tmp, &dc);
7706 ok(SUCCEEDED(hr), "Failed to get DC, i %u, hr %#lx.\n", i, hr);
7707 count = GetDIBColorTable(dc, 1, 1, &rgbquad);
7708 ok(count == 1, "Expected count 1, got %u.\n", count);
7709 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x.\n", rgbquad.rgbRed);
7710 ok(rgbquad.rgbGreen == 0x80, "Expected rgbGreen = 0x80, got %#x.\n", rgbquad.rgbGreen);
7711 ok(rgbquad.rgbBlue == 0x0, "Expected rgbBlue = 0x0, got %#x.\n", rgbquad.rgbBlue);
7712 hr = IDirectDrawSurface2_ReleaseDC(tmp, dc);
7713 ok(SUCCEEDED(hr), "Failed to release DC, i %u, hr %#lx.\n", i, hr);
7715 IDirectDrawSurface2_Release(mipmap);
7716 mipmap = tmp;
7719 hr = IDirectDrawSurface2_GetAttachedSurface(mipmap, &caps, &tmp);
7720 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
7721 IDirectDrawSurface2_Release(mipmap);
7722 refcount = IDirectDrawSurface2_Release(surface);
7723 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7724 refcount = IDirectDrawPalette_Release(palette_mipmap);
7725 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7726 refcount = IDirectDrawPalette_Release(palette);
7727 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7729 refcount = IDirectDraw2_Release(ddraw);
7730 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7731 DestroyWindow(window);
7734 static void test_p8_blit(void)
7736 IDirectDrawSurface *src, *dst, *dst_p8;
7737 DDSURFACEDESC surface_desc;
7738 unsigned int color, x;
7739 IDirectDraw2 *ddraw;
7740 IDirectDrawPalette *palette, *palette2;
7741 ULONG refcount;
7742 HWND window;
7743 HRESULT hr;
7744 PALETTEENTRY palette_entries[256];
7745 DDBLTFX fx;
7746 BOOL is_warp;
7747 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
7748 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
7749 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
7750 static const unsigned int expected[] =
7752 0x00101010, 0x00010101, 0x00020202, 0x00030303,
7753 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
7756 window = create_window();
7757 ddraw = create_ddraw();
7758 ok(!!ddraw, "Failed to create a ddraw object.\n");
7759 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7760 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
7761 is_warp = ddraw_is_warp(ddraw);
7763 memset(palette_entries, 0, sizeof(palette_entries));
7764 palette_entries[1].peGreen = 0xff;
7765 palette_entries[2].peBlue = 0xff;
7766 palette_entries[3].peFlags = 0xff;
7767 palette_entries[4].peRed = 0xff;
7768 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7769 palette_entries, &palette, NULL);
7770 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
7771 palette_entries[1].peBlue = 0xff;
7772 palette_entries[2].peGreen = 0xff;
7773 palette_entries[3].peRed = 0xff;
7774 palette_entries[4].peFlags = 0x0;
7775 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7776 palette_entries, &palette2, NULL);
7777 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
7779 memset(&surface_desc, 0, sizeof(surface_desc));
7780 surface_desc.dwSize = sizeof(surface_desc);
7781 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7782 surface_desc.dwWidth = 8;
7783 surface_desc.dwHeight = 1;
7784 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7785 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7786 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7787 surface_desc.ddpfPixelFormat.dwRGBBitCount = 8;
7788 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src, NULL);
7789 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
7790 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
7791 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
7792 hr = IDirectDrawSurface_SetPalette(dst_p8, palette2);
7793 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
7795 memset(&surface_desc, 0, sizeof(surface_desc));
7796 surface_desc.dwSize = sizeof(surface_desc);
7797 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7798 surface_desc.dwWidth = 8;
7799 surface_desc.dwHeight = 1;
7800 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7801 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7802 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
7803 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
7804 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
7805 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
7806 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
7807 surface_desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
7808 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst, NULL);
7809 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
7811 memset(&surface_desc, 0, sizeof(surface_desc));
7812 surface_desc.dwSize = sizeof(surface_desc);
7813 hr = IDirectDrawSurface_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
7814 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#lx.\n", hr);
7815 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
7816 hr = IDirectDrawSurface_Unlock(src, NULL);
7817 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#lx.\n", hr);
7819 hr = IDirectDrawSurface_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
7820 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#lx.\n", hr);
7821 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
7822 hr = IDirectDrawSurface_Unlock(dst_p8, NULL);
7823 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#lx.\n", hr);
7825 fx.dwSize = sizeof(fx);
7826 fx.dwFillColor = 0xdeadbeef;
7827 hr = IDirectDrawSurface_Blt(dst, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
7828 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
7830 hr = IDirectDrawSurface_SetPalette(src, palette);
7831 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
7832 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
7833 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
7834 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
7835 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
7836 "Failed to blit, hr %#lx.\n", hr);
7838 if (SUCCEEDED(hr))
7840 for (x = 0; x < ARRAY_SIZE(expected); x++)
7842 color = get_surface_color(dst, x, 0);
7843 /* WARP on 1709 and newer write zeroes on non-colorkeyed P8 -> RGB blits. For ckey
7844 * blits see below. */
7845 todo_wine ok(compare_color(color, expected[x], 0)
7846 || broken(is_warp && compare_color(color, 0x00000000, 0)),
7847 "Pixel %u: Got color %#x, expected %#x.\n",
7848 x, color, expected[x]);
7852 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
7853 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
7854 hr = IDirectDrawSurface7_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
7855 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
7857 hr = IDirectDrawSurface_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
7858 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#lx.\n", hr);
7859 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
7860 * surface untouched. Error checking (DDBLT_KEYSRC without a key
7861 * for example) also works as expected.
7863 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
7864 * the display mode set to P8 doesn't help either. */
7865 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
7866 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
7867 "Got unexpected P8 color key blit result.\n");
7868 hr = IDirectDrawSurface_Unlock(dst_p8, NULL);
7869 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#lx.\n", hr);
7871 IDirectDrawSurface_Release(src);
7872 IDirectDrawSurface_Release(dst);
7873 IDirectDrawSurface_Release(dst_p8);
7874 IDirectDrawPalette_Release(palette);
7875 IDirectDrawPalette_Release(palette2);
7877 refcount = IDirectDraw2_Release(ddraw);
7878 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
7879 DestroyWindow(window);
7882 static void test_material(void)
7884 IDirect3DMaterial2 *background, *material;
7885 D3DMATERIALHANDLE mat_handle, tmp;
7886 IDirect3DViewport2 *viewport;
7887 IDirect3DDevice2 *device;
7888 IDirectDrawSurface *rt;
7889 unsigned int color, i;
7890 IDirectDraw2 *ddraw;
7891 ULONG refcount;
7892 HWND window;
7893 HRESULT hr;
7894 BOOL valid;
7896 static D3DVERTEX quad[] =
7898 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
7899 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
7900 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
7901 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
7903 static const struct
7905 BOOL material;
7906 D3DCOLOR expected_color;
7908 test_data[] =
7910 {TRUE, 0x0000ff00},
7911 {FALSE, 0x00ffffff},
7913 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
7915 window = create_window();
7916 ddraw = create_ddraw();
7917 ok(!!ddraw, "Failed to create a ddraw object.\n");
7918 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7920 skip("Failed to create a 3D device, skipping test.\n");
7921 DestroyWindow(window);
7922 return;
7925 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
7926 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
7928 background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
7929 viewport = create_viewport(device, 0, 0, 640, 480);
7930 viewport_set_background(device, viewport, background);
7931 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
7932 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
7934 material = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
7935 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
7936 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#lx.\n", hr);
7938 hr = IDirect3DDevice2_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
7939 ok(SUCCEEDED(hr), "Failed to get light state, hr %#lx.\n", hr);
7940 ok(!tmp, "Got unexpected material handle %#lx.\n", tmp);
7941 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
7942 ok(SUCCEEDED(hr), "Failed to set material state, hr %#lx.\n", hr);
7943 hr = IDirect3DDevice2_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
7944 ok(SUCCEEDED(hr), "Failed to get light state, hr %#lx.\n", hr);
7945 ok(tmp == mat_handle, "Got unexpected material handle %#lx, expected %#lx.\n", tmp, mat_handle);
7946 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, 0);
7947 ok(SUCCEEDED(hr), "Failed to set material state, hr %#lx.\n", hr);
7948 hr = IDirect3DDevice2_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
7949 ok(SUCCEEDED(hr), "Failed to get light state, hr %#lx.\n", hr);
7950 ok(!tmp, "Got unexpected material handle %#lx.\n", tmp);
7952 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7954 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
7955 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
7957 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, test_data[i].material ? mat_handle : 0);
7958 ok(SUCCEEDED(hr), "Failed to set material state, hr %#lx.\n", hr);
7960 hr = IDirect3DDevice2_BeginScene(device);
7961 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
7962 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_VERTEX, quad, 4, 0);
7963 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
7964 hr = IDirect3DDevice2_EndScene(device);
7965 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
7966 color = get_surface_color(rt, 320, 240);
7967 ok(compare_color(color, test_data[i].expected_color, 1),
7968 "Got unexpected color 0x%08x, test %u.\n", color, i);
7971 destroy_material(material);
7972 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
7973 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
7974 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#lx.\n", hr);
7976 hr = IDirect3DViewport2_SetBackground(viewport, mat_handle);
7977 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#lx.\n", hr);
7978 hr = IDirect3DViewport2_GetBackground(viewport, &tmp, &valid);
7979 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#lx.\n", hr);
7980 ok(tmp == mat_handle, "Got unexpected material handle %#lx, expected %#lx.\n", tmp, mat_handle);
7981 ok(valid, "Got unexpected valid %#x.\n", valid);
7982 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7983 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
7984 color = get_surface_color(rt, 320, 240);
7985 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
7987 hr = IDirect3DViewport2_SetBackground(viewport, 0);
7988 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
7989 hr = IDirect3DViewport2_GetBackground(viewport, &tmp, &valid);
7990 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#lx.\n", hr);
7991 ok(tmp == mat_handle, "Got unexpected material handle %#lx, expected %#lx.\n", tmp, mat_handle);
7992 ok(valid, "Got unexpected valid %#x.\n", valid);
7993 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7994 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
7995 color = get_surface_color(rt, 320, 240);
7996 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
7998 destroy_viewport(device, viewport);
7999 viewport = create_viewport(device, 0, 0, 640, 480);
8001 hr = IDirect3DViewport2_GetBackground(viewport, &tmp, &valid);
8002 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#lx.\n", hr);
8003 ok(!tmp, "Got unexpected material handle %#lx.\n", tmp);
8004 ok(!valid, "Got unexpected valid %#x.\n", valid);
8005 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8006 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
8007 color = get_surface_color(rt, 320, 240);
8008 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x.\n", color);
8010 destroy_viewport(device, viewport);
8011 destroy_material(background);
8012 destroy_material(material);
8013 IDirectDrawSurface_Release(rt);
8014 refcount = IDirect3DDevice2_Release(device);
8015 ok(!refcount, "Device has %lu references left.\n", refcount);
8016 refcount = IDirectDraw2_Release(ddraw);
8017 ok(!refcount, "Ddraw object has %lu references left.\n", refcount);
8018 DestroyWindow(window);
8021 static void test_lighting(void)
8023 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8024 static D3DMATRIX mat =
8026 1.0f, 0.0f, 0.0f, 0.0f,
8027 0.0f, 1.0f, 0.0f, 0.0f,
8028 0.0f, 0.0f, 1.0f, 0.0f,
8029 0.0f, 0.0f, 0.0f, 1.0f,
8031 mat_singular =
8033 1.0f, 0.0f, 1.0f, 0.0f,
8034 0.0f, 1.0f, 0.0f, 0.0f,
8035 1.0f, 0.0f, 1.0f, 0.0f,
8036 0.0f, 0.0f, 0.5f, 1.0f,
8038 mat_transf =
8040 0.0f, 0.0f, 1.0f, 0.0f,
8041 0.0f, 1.0f, 0.0f, 0.0f,
8042 -1.0f, 0.0f, 0.0f, 0.0f,
8043 10.f, 10.0f, 10.0f, 1.0f,
8045 mat_nonaffine =
8047 1.0f, 0.0f, 0.0f, 0.0f,
8048 0.0f, 1.0f, 0.0f, 0.0f,
8049 0.0f, 0.0f, 1.0f, -1.0f,
8050 10.f, 10.0f, 10.0f, 0.0f,
8052 static D3DLVERTEX unlitquad[] =
8054 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
8055 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
8056 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
8057 {{ 0.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
8059 litquad[] =
8061 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
8062 {{-1.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
8063 {{ 0.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
8064 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
8066 static D3DVERTEX unlitnquad[] =
8068 {{0.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
8069 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
8070 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
8071 {{1.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
8073 litnquad[] =
8075 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
8076 {{0.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
8077 {{1.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
8078 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
8080 nquad[] =
8082 {{-1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
8083 {{-1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
8084 {{ 1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
8085 {{ 1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
8087 rotatedquad[] =
8089 {{-10.0f}, {-11.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
8090 {{-10.0f}, { -9.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
8091 {{-10.0f}, { -9.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
8092 {{-10.0f}, {-11.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
8094 translatedquad[] =
8096 {{-11.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
8097 {{-11.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
8098 {{ -9.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
8099 {{ -9.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
8101 static WORD indices[] = {0, 1, 2, 2, 3, 0};
8102 static const struct
8104 D3DMATRIX *world_matrix;
8105 void *quad;
8106 DWORD expected;
8107 const char *message;
8109 tests[] =
8111 {&mat, nquad, 0x000060ff, "Lit quad with light"},
8112 {&mat_singular, nquad, 0x00004db4, "Lit quad with singular world matrix"},
8113 {&mat_transf, rotatedquad, 0x000060ff, "Lit quad with transformation matrix"},
8114 {&mat_nonaffine, translatedquad, 0x000060ff, "Lit quad with non-affine matrix"},
8117 IDirect3DViewport2 *viewport, *viewport2;
8118 D3DMATERIALHANDLE mat_handle;
8119 IDirect3DMaterial2 *material;
8120 IDirect3DDevice2 *device;
8121 IDirectDrawSurface *rt;
8122 IDirect3DLight *light;
8123 unsigned int color, i;
8124 D3DLIGHT2 light_desc;
8125 IDirectDraw2 *ddraw;
8126 IDirect3D2 *d3d;
8127 ULONG refcount;
8128 HWND window;
8129 HRESULT hr;
8131 window = create_window();
8132 ddraw = create_ddraw();
8133 ok(!!ddraw, "Failed to create a ddraw object.\n");
8134 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8136 skip("Failed to create a 3D device, skipping test.\n");
8137 DestroyWindow(window);
8138 return;
8141 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
8142 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8144 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
8145 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8147 viewport = create_viewport(device, 0, 0, 640, 480);
8148 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
8149 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8151 material = create_diffuse_and_ambient_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
8152 viewport_set_background(device, viewport, material);
8154 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8155 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
8157 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
8158 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
8159 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
8160 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#lx.\n", hr);
8161 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
8162 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#lx.\n", hr);
8163 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
8164 ok(SUCCEEDED(hr), "Failed to disable zbuffer, hr %#lx.\n", hr);
8165 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
8166 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#lx.\n", hr);
8167 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
8168 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#lx.\n", hr);
8170 hr = IDirect3DDevice2_BeginScene(device);
8171 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
8173 /* There is no D3DRENDERSTATE_LIGHTING on ddraw < 7. */
8174 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
8175 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#lx.\n", hr);
8176 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_LVERTEX, unlitquad,
8177 4, indices, 6, 0);
8178 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
8180 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
8181 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#lx.\n", hr);
8182 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_LVERTEX, litquad,
8183 4, indices, 6, 0);
8184 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
8186 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
8187 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#lx.\n", hr);
8188 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, unlitnquad,
8189 4, indices, 6, 0);
8190 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
8192 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
8193 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#lx.\n", hr);
8194 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, litnquad,
8195 4, indices, 6, 0);
8196 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
8198 hr = IDirect3DDevice2_EndScene(device);
8199 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
8201 color = get_surface_color(rt, 160, 360);
8202 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
8203 color = get_surface_color(rt, 160, 120);
8204 ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
8205 color = get_surface_color(rt, 480, 360);
8206 ok(color == 0x00ffffff, "Unlit quad with normals has color 0x%08x.\n", color);
8207 color = get_surface_color(rt, 480, 120);
8208 ok(color == 0x00ffffff, "Lit quad with normals has color 0x%08x.\n", color);
8210 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
8211 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8212 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
8213 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8214 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_AMBIENT, 0xff002000);
8215 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8217 hr = IDirect3D2_CreateLight(d3d, &light, NULL);
8218 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8219 memset(&light_desc, 0, sizeof(light_desc));
8220 light_desc.dwSize = sizeof(light_desc);
8221 light_desc.dltType = D3DLIGHT_DIRECTIONAL;
8222 light_desc.dcvColor.r = 0.0f;
8223 light_desc.dcvColor.g = 0.25f;
8224 light_desc.dcvColor.b = 1.0f;
8225 light_desc.dcvColor.a = 1.0f;
8226 light_desc.dvDirection.z = 1.0f;
8227 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
8228 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8229 hr = IDirect3DViewport2_AddLight(viewport, light);
8230 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8231 hr = IDirect3DViewport2_AddLight(viewport, light);
8232 ok(hr == D3DERR_LIGHTHASVIEWPORT, "Got unexpected hr %#lx.\n", hr);
8234 viewport2 = create_viewport(device, 0, 0, 640, 480);
8235 hr = IDirect3DViewport2_AddLight(viewport2, light);
8236 ok(hr == D3DERR_LIGHTHASVIEWPORT, "Got unexpected hr %#lx.\n", hr);
8237 destroy_viewport(device, viewport2);
8239 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8240 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8242 hr = IDirect3DDevice2_BeginScene(device);
8243 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8245 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, nquad,
8246 4, indices, 6, 0);
8247 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8249 hr = IDirect3DDevice2_EndScene(device);
8250 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8252 color = get_surface_color(rt, 320, 240);
8253 ok(color == 0x00002000, "Lit quad with no light has color 0x%08x.\n", color);
8255 light_desc.dwFlags = D3DLIGHT_ACTIVE;
8256 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
8257 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8258 hr = IDirect3DViewport2_DeleteLight(viewport, light);
8259 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8260 light_desc.dwFlags = 0;
8261 hr = IDirect3DLight_GetLight(light, (D3DLIGHT *)&light_desc);
8262 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8263 ok(light_desc.dwFlags == D3DLIGHT_ACTIVE, "Got unexpected flags %#lx.\n", light_desc.dwFlags);
8265 hr = IDirect3DViewport2_AddLight(viewport, light);
8266 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8267 for (i = 0; i < ARRAY_SIZE(tests); ++i)
8269 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
8270 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
8272 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8273 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
8275 hr = IDirect3DDevice2_BeginScene(device);
8276 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
8278 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX,
8279 tests[i].quad, 4, indices, 6, 0);
8280 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
8282 hr = IDirect3DDevice2_EndScene(device);
8283 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
8285 color = get_surface_color(rt, 320, 240);
8286 ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
8289 hr = IDirect3DViewport2_DeleteLight(viewport, light);
8290 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#lx.\n", hr);
8291 IDirect3DLight_Release(light);
8292 destroy_material(material);
8293 destroy_viewport(device, viewport);
8294 IDirectDrawSurface2_Release(rt);
8295 refcount = IDirect3DDevice2_Release(device);
8296 ok(!refcount, "Device has %lu references left.\n", refcount);
8297 IDirect3D2_Release(d3d);
8298 refcount = IDirectDraw2_Release(ddraw);
8299 ok(!refcount, "Ddraw object has %lu references left.\n", refcount);
8300 DestroyWindow(window);
8303 static void test_specular_lighting(void)
8305 static const unsigned int vertices_side = 5;
8306 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
8307 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
8308 static D3DMATRIX mat =
8310 1.0f, 0.0f, 0.0f, 0.0f,
8311 0.0f, 1.0f, 0.0f, 0.0f,
8312 0.0f, 0.0f, 1.0f, 0.0f,
8313 0.0f, 0.0f, 0.0f, 1.0f,
8315 static D3DLIGHT2 directional =
8317 sizeof(D3DLIGHT2),
8318 D3DLIGHT_DIRECTIONAL,
8319 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
8320 {{0.0f}, {0.0f}, {0.0f}},
8321 {{0.0f}, {0.0f}, {1.0f}},
8323 point =
8325 sizeof(D3DLIGHT2),
8326 D3DLIGHT_POINT,
8327 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
8328 {{0.0f}, {0.0f}, {0.0f}},
8329 {{0.0f}, {0.0f}, {0.0f}},
8330 100.0f,
8331 0.0f,
8332 0.0f, 0.0f, 1.0f,
8334 spot =
8336 sizeof(D3DLIGHT2),
8337 D3DLIGHT_SPOT,
8338 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
8339 {{0.0f}, {0.0f}, {0.0f}},
8340 {{0.0f}, {0.0f}, {1.0f}},
8341 100.0f,
8342 1.0f,
8343 0.0f, 0.0f, 1.0f,
8344 M_PI / 12.0f, M_PI / 3.0f
8346 parallelpoint =
8348 sizeof(D3DLIGHT2),
8349 D3DLIGHT_PARALLELPOINT,
8350 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
8351 {{0.5f}, {0.0f}, {-1.0f}},
8352 {{0.0f}, {0.0f}, {0.0f}},
8354 point_side =
8356 sizeof(D3DLIGHT2),
8357 D3DLIGHT_POINT,
8358 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
8359 {{-1.1f}, {0.0f}, {1.1f}},
8360 {{0.0f}, {0.0f}, {0.0f}},
8361 100.0f,
8362 0.0f,
8363 1.0f, 0.0f, 0.0f,
8365 point_far =
8367 sizeof(D3DLIGHT2),
8368 D3DLIGHT_POINT,
8369 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
8370 {{0.0f}, {0.0f}, {0.1f}},
8371 {{0.0f}, {0.0f}, {0.0f}},
8372 1.0f,
8373 0.0f,
8374 1.0f, 0.0f, 0.0f,
8376 static const struct expected_color
8378 unsigned int x, y, color;
8380 expected_directional_local[] =
8382 {160, 120, 0x003c3c3c},
8383 {320, 120, 0x00717171},
8384 {480, 120, 0x003c3c3c},
8385 {160, 240, 0x00717171},
8386 {320, 240, 0x00ffffff},
8387 {480, 240, 0x00717171},
8388 {160, 360, 0x003c3c3c},
8389 {320, 360, 0x00717171},
8390 {480, 360, 0x003c3c3c},
8392 expected_point_local[] =
8394 {160, 120, 0x00000000},
8395 {320, 120, 0x00090909},
8396 {480, 120, 0x00000000},
8397 {160, 240, 0x00090909},
8398 {320, 240, 0x00fafafa},
8399 {480, 240, 0x00090909},
8400 {160, 360, 0x00000000},
8401 {320, 360, 0x00090909},
8402 {480, 360, 0x00000000},
8404 expected_spot_local[] =
8406 {160, 120, 0x00000000},
8407 {320, 120, 0x00020202},
8408 {480, 120, 0x00000000},
8409 {160, 240, 0x00020202},
8410 {320, 240, 0x00fafafa},
8411 {480, 240, 0x00020202},
8412 {160, 360, 0x00000000},
8413 {320, 360, 0x00020202},
8414 {480, 360, 0x00000000},
8416 expected_parallelpoint[] =
8418 {160, 120, 0x00050505},
8419 {320, 120, 0x002c2c2c},
8420 {480, 120, 0x006e6e6e},
8421 {160, 240, 0x00090909},
8422 {320, 240, 0x00717171},
8423 {480, 240, 0x00ffffff},
8424 {160, 360, 0x00050505},
8425 {320, 360, 0x002c2c2c},
8426 {480, 360, 0x006e6e6e},
8428 expected_point_far[] =
8430 {160, 120, 0x00000000},
8431 {320, 120, 0x00000000},
8432 {480, 120, 0x00000000},
8433 {160, 240, 0x00000000},
8434 {320, 240, 0x00ffffff},
8435 {480, 240, 0x00000000},
8436 {160, 360, 0x00000000},
8437 {320, 360, 0x00000000},
8438 {480, 360, 0x00000000},
8440 expected_zero[] =
8442 {160, 120, 0x00000000},
8443 {320, 120, 0x00000000},
8444 {480, 120, 0x00000000},
8445 {160, 240, 0x00000000},
8446 {320, 240, 0x00000000},
8447 {480, 240, 0x00000000},
8448 {160, 360, 0x00000000},
8449 {320, 360, 0x00000000},
8450 {480, 360, 0x00000000},
8452 static const struct
8454 D3DLIGHT2 *light;
8455 float specular_power;
8456 const struct expected_color *expected;
8457 unsigned int expected_count;
8459 tests[] =
8461 {&directional, 30.0f, expected_directional_local, ARRAY_SIZE(expected_directional_local)},
8462 {&point, 30.0f, expected_point_local, ARRAY_SIZE(expected_point_local)},
8463 {&spot, 30.0f, expected_spot_local, ARRAY_SIZE(expected_spot_local)},
8464 {&parallelpoint, 30.0f, expected_parallelpoint, ARRAY_SIZE(expected_parallelpoint)},
8465 {&point_side, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
8466 {&point_far, 1.0f, expected_point_far, ARRAY_SIZE(expected_point_far)},
8467 {&directional, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
8468 {&point, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
8469 {&spot, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
8470 {&parallelpoint, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
8471 {&point_far, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
8473 IDirect3D2 *d3d;
8474 IDirect3DDevice2 *device;
8475 IDirectDraw2 *ddraw;
8476 IDirectDrawSurface *rt;
8477 IDirect3DViewport2 *viewport;
8478 IDirect3DMaterial2 *material, *background_material;
8479 unsigned int color, i, j, x, y;
8480 IDirect3DLight *light;
8481 D3DMATERIALHANDLE mat_handle;
8482 ULONG refcount;
8483 HWND window;
8484 HRESULT hr;
8485 D3DVERTEX *quad;
8486 WORD *indices;
8488 window = create_window();
8489 ddraw = create_ddraw();
8490 ok(!!ddraw, "Failed to create a ddraw object.\n");
8491 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8493 skip("Failed to create a 3D device, skipping test.\n");
8494 DestroyWindow(window);
8495 return;
8498 quad = malloc(vertices_side * vertices_side * sizeof(*quad));
8499 indices = malloc(indices_count * sizeof(*indices));
8500 for (i = 0, y = 0; y < vertices_side; ++y)
8502 for (x = 0; x < vertices_side; ++x)
8504 quad[i].x = x * 2.0f / (vertices_side - 1) - 1.0f;
8505 quad[i].y = y * 2.0f / (vertices_side - 1) - 1.0f;
8506 quad[i].z = 1.0f;
8507 quad[i].nx = 0.0f;
8508 quad[i].ny = 0.0f;
8509 quad[i].nz = -1.0f;
8510 quad[i].tu = 0.0f;
8511 quad[i++].tv = 0.0f;
8514 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
8516 for (x = 0; x < (vertices_side - 1); ++x)
8518 indices[i++] = y * vertices_side + x + 1;
8519 indices[i++] = y * vertices_side + x;
8520 indices[i++] = (y + 1) * vertices_side + x;
8521 indices[i++] = y * vertices_side + x + 1;
8522 indices[i++] = (y + 1) * vertices_side + x;
8523 indices[i++] = (y + 1) * vertices_side + x + 1;
8527 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
8528 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#lx.\n", hr);
8530 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
8531 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
8533 viewport = create_viewport(device, 0, 0, 640, 480);
8534 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
8535 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
8537 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
8538 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
8539 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
8540 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#lx.\n", hr);
8541 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
8542 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#lx.\n", hr);
8543 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
8544 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#lx.\n", hr);
8545 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
8546 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#lx.\n", hr);
8548 background_material = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
8549 viewport_set_background(device, viewport, background_material);
8551 hr = IDirect3D2_CreateLight(d3d, &light, NULL);
8552 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#lx.\n", hr);
8553 hr = IDirect3DViewport2_AddLight(viewport, light);
8554 ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#lx.\n", hr);
8556 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
8557 ok(SUCCEEDED(hr), "Failed to enable specular lighting, hr %#lx.\n", hr);
8559 for (i = 0; i < ARRAY_SIZE(tests); ++i)
8561 tests[i].light->dwFlags = D3DLIGHT_ACTIVE;
8562 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)tests[i].light);
8563 ok(SUCCEEDED(hr), "Failed to set light, hr %#lx.\n", hr);
8565 material = create_specular_material(device, 1.0f, 1.0f, 1.0f, 1.0f, tests[i].specular_power);
8566 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
8567 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#lx.\n", hr);
8568 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
8569 ok(SUCCEEDED(hr), "Failed to set material state, hr %#lx.\n", hr);
8571 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8572 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
8574 hr = IDirect3DDevice2_BeginScene(device);
8575 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
8577 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX,
8578 quad, vertices_side * vertices_side, indices, indices_count, 0);
8579 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
8581 hr = IDirect3DDevice2_EndScene(device);
8582 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
8584 for (j = 0; j < tests[i].expected_count; ++j)
8586 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
8587 ok(compare_color(color, tests[i].expected[j].color, 1),
8588 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
8589 tests[i].expected[j].color, tests[i].expected[j].x,
8590 tests[i].expected[j].y, color, i);
8593 destroy_material(material);
8596 hr = IDirect3DViewport2_DeleteLight(viewport, light);
8597 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#lx.\n", hr);
8598 IDirect3DLight_Release(light);
8599 destroy_material(background_material);
8600 destroy_viewport(device, viewport);
8601 IDirectDrawSurface2_Release(rt);
8602 refcount = IDirect3DDevice2_Release(device);
8603 ok(!refcount, "Device has %lu references left.\n", refcount);
8604 IDirect3D2_Release(d3d);
8605 refcount = IDirectDraw2_Release(ddraw);
8606 ok(!refcount, "Ddraw object has %lu references left.\n", refcount);
8607 DestroyWindow(window);
8608 free(indices);
8609 free(quad);
8612 static void test_palette_gdi(void)
8614 IDirectDrawSurface *surface, *primary;
8615 DDSURFACEDESC surface_desc;
8616 unsigned int color, i;
8617 IDirectDraw2 *ddraw;
8618 IDirectDrawPalette *palette, *palette2;
8619 ULONG refcount;
8620 HWND window;
8621 HRESULT hr;
8622 PALETTEENTRY palette_entries[256];
8623 HDC dc;
8624 DDBLTFX fx;
8625 RECT r;
8627 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
8628 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
8629 * not the point of this test. */
8630 static const RGBQUAD expected1[] =
8632 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8633 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
8635 static const RGBQUAD expected2[] =
8637 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8638 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
8640 static const RGBQUAD expected3[] =
8642 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
8643 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
8645 HPALETTE ddraw_palette_handle;
8646 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
8647 RGBQUAD rgbquad[255];
8648 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
8650 window = create_window();
8651 ddraw = create_ddraw();
8652 ok(!!ddraw, "Failed to create a ddraw object.\n");
8653 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8654 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
8656 memset(&surface_desc, 0, sizeof(surface_desc));
8657 surface_desc.dwSize = sizeof(surface_desc);
8658 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8659 surface_desc.dwWidth = 16;
8660 surface_desc.dwHeight = 16;
8661 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8662 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
8663 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8664 surface_desc.ddpfPixelFormat.dwRGBBitCount = 8;
8665 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8666 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8668 /* Avoid colors from the Windows default palette. */
8669 memset(palette_entries, 0, sizeof(palette_entries));
8670 palette_entries[1].peRed = 0x01;
8671 palette_entries[2].peGreen = 0x02;
8672 palette_entries[3].peBlue = 0x03;
8673 palette_entries[4].peRed = 0x13;
8674 palette_entries[4].peGreen = 0x14;
8675 palette_entries[4].peBlue = 0x15;
8676 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8677 palette_entries, &palette, NULL);
8678 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
8680 /* If there is no palette assigned and the display mode is not 8 bpp, some
8681 * drivers refuse to create a DC while others allow it. If a DC is created,
8682 * the DIB color table is uninitialized and contains random colors. No error
8683 * is generated when trying to read pixels and random garbage is returned.
8685 * The most likely explanation is that if the driver creates a DC, it (or
8686 * the higher-level runtime) uses GetSystemPaletteEntries to find the
8687 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
8688 * contains uninitialized garbage. See comments below for the P8 case. */
8690 hr = IDirectDrawSurface_SetPalette(surface, palette);
8691 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
8692 hr = IDirectDrawSurface_GetDC(surface, &dc);
8693 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
8694 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8695 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8696 "Got unexpected palette %p, expected %p.\n",
8697 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8699 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8700 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8701 for (i = 0; i < ARRAY_SIZE(expected1); i++)
8703 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
8704 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8705 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8706 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
8708 for (; i < ARRAY_SIZE(rgbquad); i++)
8710 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8711 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8712 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8715 /* Update the palette while the DC is in use. This does not modify the DC. */
8716 palette_entries[4].peRed = 0x23;
8717 palette_entries[4].peGreen = 0x24;
8718 palette_entries[4].peBlue = 0x25;
8719 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
8720 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#lx.\n", hr);
8722 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8723 ok(i == 1, "Expected count 1, got %u.\n", i);
8724 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8725 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8726 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8727 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8729 /* Neither does re-setting the palette. */
8730 hr = IDirectDrawSurface_SetPalette(surface, NULL);
8731 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
8732 hr = IDirectDrawSurface_SetPalette(surface, palette);
8733 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
8735 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8736 ok(i == 1, "Expected count 1, got %u.\n", i);
8737 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8738 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8739 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8740 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8742 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8743 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
8745 /* Refresh the DC. This updates the palette. */
8746 hr = IDirectDrawSurface_GetDC(surface, &dc);
8747 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
8748 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8749 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8750 for (i = 0; i < ARRAY_SIZE(expected2); i++)
8752 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8753 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8754 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8755 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8757 for (; i < ARRAY_SIZE(rgbquad); i++)
8759 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8760 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8761 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8763 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8764 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
8766 refcount = IDirectDrawSurface_Release(surface);
8767 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8769 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
8770 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
8771 if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8773 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8774 IDirectDrawPalette_Release(palette);
8775 IDirectDraw2_Release(ddraw);
8776 DestroyWindow(window);
8777 return;
8779 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
8781 memset(&surface_desc, 0, sizeof(surface_desc));
8782 surface_desc.dwSize = sizeof(surface_desc);
8783 surface_desc.dwFlags = DDSD_CAPS;
8784 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8785 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8786 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8788 memset(&fx, 0, sizeof(fx));
8789 fx.dwSize = sizeof(fx);
8790 fx.dwFillColor = 3;
8791 SetRect(&r, 0, 0, 319, 479);
8792 hr = IDirectDrawSurface_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8793 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#lx.\n", hr);
8794 SetRect(&r, 320, 0, 639, 479);
8795 fx.dwFillColor = 4;
8796 hr = IDirectDrawSurface_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8797 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#lx.\n", hr);
8799 hr = IDirectDrawSurface_SetPalette(primary, palette);
8800 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
8801 hr = IDirectDrawSurface_GetDC(primary, &dc);
8802 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
8804 color = GetPixel(dc, 160, 240);
8805 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
8806 color = GetPixel(dc, 480, 240);
8807 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
8809 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8810 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8811 "Got unexpected palette %p, expected %p.\n",
8812 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8813 SelectPalette(dc, ddraw_palette_handle, FALSE);
8815 /* The primary uses the system palette. In exclusive mode, the system palette matches
8816 * the ddraw palette attached to the primary, so the result is what you would expect
8817 * from a regular surface. Tests for the interaction between the ddraw palette and
8818 * the system palette are not included pending an application that depends on this.
8819 * The relation between those causes problems on Windows Vista and newer for games
8820 * like Age of Empires or StarCraft. Don't emulate it without a real need. */
8821 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8822 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8823 for (i = 0; i < ARRAY_SIZE(expected2); i++)
8825 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8826 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8827 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8828 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8830 for (; i < ARRAY_SIZE(rgbquad); i++)
8832 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8833 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8834 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8836 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
8837 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
8839 memset(&surface_desc, 0, sizeof(surface_desc));
8840 surface_desc.dwSize = sizeof(surface_desc);
8841 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8842 surface_desc.dwWidth = 16;
8843 surface_desc.dwHeight = 16;
8844 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8845 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8846 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8848 /* Here the offscreen surface appears to use the primary's palette,
8849 * but in all likelihood it is actually the system palette. */
8850 hr = IDirectDrawSurface_GetDC(surface, &dc);
8851 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
8852 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8853 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8854 for (i = 0; i < ARRAY_SIZE(expected2); i++)
8856 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8857 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8858 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8859 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8861 for (; i < ARRAY_SIZE(rgbquad); i++)
8863 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8864 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8865 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8867 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8868 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
8870 /* On real hardware a change to the primary surface's palette applies immediately,
8871 * even on device contexts from offscreen surfaces that do not have their own
8872 * palette. On the testbot VMs this is not the case. Don't test this until we
8873 * know of an application that depends on this. */
8875 memset(palette_entries, 0, sizeof(palette_entries));
8876 palette_entries[1].peBlue = 0x40;
8877 palette_entries[2].peRed = 0x40;
8878 palette_entries[3].peGreen = 0x40;
8879 palette_entries[4].peRed = 0x12;
8880 palette_entries[4].peGreen = 0x34;
8881 palette_entries[4].peBlue = 0x56;
8882 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8883 palette_entries, &palette2, NULL);
8884 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
8885 hr = IDirectDrawSurface_SetPalette(surface, palette2);
8886 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
8888 /* A palette assigned to the offscreen surface overrides the primary / system
8889 * palette. */
8890 hr = IDirectDrawSurface_GetDC(surface, &dc);
8891 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
8892 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8893 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8894 for (i = 0; i < ARRAY_SIZE(expected3); i++)
8896 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
8897 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8898 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8899 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
8901 for (; i < ARRAY_SIZE(rgbquad); i++)
8903 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8904 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8905 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8907 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8908 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
8910 refcount = IDirectDrawSurface_Release(surface);
8911 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8913 /* The Windows 8 testbot keeps extra references to the primary and
8914 * backbuffer while in 8 bpp mode. */
8915 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
8916 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#lx.\n", hr);
8918 refcount = IDirectDrawSurface_Release(primary);
8919 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8920 refcount = IDirectDrawPalette_Release(palette2);
8921 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8922 refcount = IDirectDrawPalette_Release(palette);
8923 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8924 refcount = IDirectDraw2_Release(ddraw);
8925 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8926 DestroyWindow(window);
8929 static void test_palette_alpha(void)
8931 IDirectDrawSurface *surface1;
8932 IDirectDrawSurface2 *surface;
8933 DDSURFACEDESC surface_desc;
8934 IDirectDraw2 *ddraw;
8935 IDirectDrawPalette *palette;
8936 ULONG refcount;
8937 HWND window;
8938 HRESULT hr;
8939 PALETTEENTRY palette_entries[256];
8940 unsigned int i;
8941 static const struct
8943 DWORD caps, flags;
8944 BOOL attach_allowed;
8945 const char *name;
8947 test_data[] =
8949 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
8950 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
8951 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
8954 window = create_window();
8955 ddraw = create_ddraw();
8956 ok(!!ddraw, "Failed to create a ddraw object.\n");
8957 if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8959 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8960 IDirectDraw2_Release(ddraw);
8961 DestroyWindow(window);
8962 return;
8964 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8965 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
8967 memset(palette_entries, 0, sizeof(palette_entries));
8968 palette_entries[1].peFlags = 0x42;
8969 palette_entries[2].peFlags = 0xff;
8970 palette_entries[3].peFlags = 0x80;
8971 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
8972 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
8974 memset(palette_entries, 0x66, sizeof(palette_entries));
8975 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8976 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#lx.\n", hr);
8977 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8978 palette_entries[0].peFlags);
8979 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8980 palette_entries[1].peFlags);
8981 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8982 palette_entries[2].peFlags);
8983 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8984 palette_entries[3].peFlags);
8986 IDirectDrawPalette_Release(palette);
8988 memset(palette_entries, 0, sizeof(palette_entries));
8989 palette_entries[1].peFlags = 0x42;
8990 palette_entries[1].peRed = 0xff;
8991 palette_entries[2].peFlags = 0xff;
8992 palette_entries[3].peFlags = 0x80;
8993 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
8994 palette_entries, &palette, NULL);
8995 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
8997 memset(palette_entries, 0x66, sizeof(palette_entries));
8998 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8999 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#lx.\n", hr);
9000 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9001 palette_entries[0].peFlags);
9002 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9003 palette_entries[1].peFlags);
9004 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
9005 palette_entries[2].peFlags);
9006 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
9007 palette_entries[3].peFlags);
9009 for (i = 0; i < ARRAY_SIZE(test_data); i++)
9011 memset(&surface_desc, 0, sizeof(surface_desc));
9012 surface_desc.dwSize = sizeof(surface_desc);
9013 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
9014 surface_desc.dwWidth = 128;
9015 surface_desc.dwHeight = 128;
9016 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
9017 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
9018 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#lx.\n", test_data[i].name, hr);
9019 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
9020 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#lx.\n", hr);
9021 IDirectDrawSurface_Release(surface1);
9023 hr = IDirectDrawSurface2_SetPalette(surface, palette);
9024 if (test_data[i].attach_allowed)
9025 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#lx.\n", test_data[i].name, hr);
9026 else
9027 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#lx, %s surface.\n", hr, test_data[i].name);
9029 if (SUCCEEDED(hr))
9031 HDC dc;
9032 RGBQUAD rgbquad;
9033 UINT retval;
9035 hr = IDirectDrawSurface2_GetDC(surface, &dc);
9036 ok(SUCCEEDED(hr) || broken(hr == DDERR_CANTCREATEDC) /* Win2k testbot */,
9037 "Failed to get DC, hr %#lx, %s surface.\n", hr, test_data[i].name);
9038 if (SUCCEEDED(hr))
9040 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
9041 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
9042 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
9043 rgbquad.rgbRed, test_data[i].name);
9044 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
9045 rgbquad.rgbGreen, test_data[i].name);
9046 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
9047 rgbquad.rgbBlue, test_data[i].name);
9048 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
9049 rgbquad.rgbReserved, test_data[i].name);
9050 hr = IDirectDrawSurface2_ReleaseDC(surface, dc);
9051 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
9054 IDirectDrawSurface2_Release(surface);
9057 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
9058 memset(&surface_desc, 0, sizeof(surface_desc));
9059 surface_desc.dwSize = sizeof(surface_desc);
9060 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9061 surface_desc.dwWidth = 128;
9062 surface_desc.dwHeight = 128;
9063 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9064 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
9065 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
9066 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
9067 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
9068 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
9069 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
9070 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
9071 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9072 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
9073 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#lx.\n", hr);
9074 IDirectDrawSurface_Release(surface1);
9076 hr = IDirectDrawSurface2_SetPalette(surface, palette);
9077 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#lx.\n", hr);
9078 IDirectDrawSurface2_Release(surface);
9080 /* The Windows 8 testbot keeps extra references to the primary
9081 * while in 8 bpp mode. */
9082 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
9083 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#lx.\n", hr);
9085 refcount = IDirectDrawPalette_Release(palette);
9086 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
9087 refcount = IDirectDraw2_Release(ddraw);
9088 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
9089 DestroyWindow(window);
9092 static void test_lost_device(void)
9094 IDirectDrawSurface *surface, *back_buffer, *back_buffer2, *ds;
9095 IDirectDrawSurface *sysmem_surface, *vidmem_surface;
9096 DDSURFACEDESC surface_desc;
9097 HWND window1, window2;
9098 IDirectDraw2 *ddraw;
9099 ULONG refcount;
9100 DDSCAPS caps;
9101 HRESULT hr;
9102 BOOL ret;
9104 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9105 0, 0, 640, 480, 0, 0, 0, 0);
9106 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9107 0, 0, 640, 480, 0, 0, 0, 0);
9108 ddraw = create_ddraw();
9109 ok(!!ddraw, "Failed to create a ddraw object.\n");
9110 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9111 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9113 memset(&surface_desc, 0, sizeof(surface_desc));
9114 surface_desc.dwSize = sizeof(surface_desc);
9115 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
9116 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
9117 surface_desc.dwBackBufferCount = 1;
9118 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9119 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9121 memset(&surface_desc, 0, sizeof(surface_desc));
9122 surface_desc.dwSize = sizeof(surface_desc);
9123 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
9124 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
9125 surface_desc.dwWidth = 100;
9126 surface_desc.dwHeight = 100;
9127 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
9128 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9130 memset(&surface_desc, 0, sizeof(surface_desc));
9131 surface_desc.dwSize = sizeof(surface_desc);
9132 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9133 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
9134 surface_desc.dwWidth = 64;
9135 surface_desc.dwHeight = 64;
9136 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
9137 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
9138 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
9139 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
9140 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
9141 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
9142 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &surface_desc, &vidmem_surface, NULL)))
9144 skip("Failed to create video memory surface, skipping related tests.\n");
9145 vidmem_surface = NULL;
9148 hr = IDirectDrawSurface_IsLost(surface);
9149 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9150 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
9151 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9152 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9153 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9154 if (vidmem_surface)
9156 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9157 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9160 ret = SetForegroundWindow(GetDesktopWindow());
9161 ok(ret, "Failed to set foreground window.\n");
9162 hr = IDirectDrawSurface_IsLost(surface);
9163 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9164 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
9165 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9166 hr = IDirectDrawSurface_Restore(surface);
9167 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
9168 hr = IDirectDrawSurface_IsLost(surface);
9169 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9170 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9171 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9172 hr = IDirectDrawSurface_Restore(sysmem_surface);
9173 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9174 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9175 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9176 if (vidmem_surface)
9178 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9179 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9180 hr = IDirectDrawSurface_Restore(vidmem_surface);
9181 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
9182 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9183 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9186 ret = SetForegroundWindow(window1);
9187 ok(ret, "Failed to set foreground window.\n");
9188 hr = IDirectDrawSurface_IsLost(surface);
9189 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9190 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
9191 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9192 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9193 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9194 if (vidmem_surface)
9196 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9197 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9200 hr = restore_surfaces(ddraw);
9201 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9202 hr = IDirectDrawSurface_IsLost(surface);
9203 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9204 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
9205 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9206 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9207 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9208 if (vidmem_surface)
9210 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9211 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9214 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
9215 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9216 hr = IDirectDrawSurface_IsLost(surface);
9217 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9218 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
9219 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9220 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9221 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9222 if (vidmem_surface)
9224 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9225 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9228 /* Trying to restore the primary will crash, probably because flippable
9229 * surfaces can't exist in DDSCL_NORMAL. */
9230 IDirectDrawSurface_Release(surface);
9231 memset(&surface_desc, 0, sizeof(surface_desc));
9232 surface_desc.dwSize = sizeof(surface_desc);
9233 surface_desc.dwFlags = DDSD_CAPS;
9234 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
9235 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9236 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9237 hr = restore_surfaces(ddraw);
9238 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9240 hr = IDirectDrawSurface_IsLost(surface);
9241 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9243 ret = SetForegroundWindow(GetDesktopWindow());
9244 ok(ret, "Failed to set foreground window.\n");
9245 hr = IDirectDrawSurface_IsLost(surface);
9246 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9247 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9248 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9249 if (vidmem_surface)
9251 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9252 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9255 ret = SetForegroundWindow(window1);
9256 ok(ret, "Failed to set foreground window.\n");
9257 hr = IDirectDrawSurface_IsLost(surface);
9258 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9259 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9260 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9261 if (vidmem_surface)
9263 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9264 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9267 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9268 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9269 hr = IDirectDrawSurface_IsLost(surface);
9270 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9271 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9272 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9273 if (vidmem_surface)
9275 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9276 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9279 hr = restore_surfaces(ddraw);
9280 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9281 hr = IDirectDrawSurface_IsLost(surface);
9282 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9283 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9284 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9285 if (vidmem_surface)
9287 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9288 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9291 IDirectDrawSurface_Release(surface);
9292 memset(&surface_desc, 0, sizeof(surface_desc));
9293 surface_desc.dwSize = sizeof(surface_desc);
9294 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
9295 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
9296 surface_desc.dwBackBufferCount = 2;
9297 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9298 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9300 ds = NULL;
9301 memset(&surface_desc, 0, sizeof(surface_desc));
9302 surface_desc.dwSize = sizeof(surface_desc);
9303 hr = IDirectDrawSurface2_GetSurfaceDesc(surface, &surface_desc);
9304 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
9306 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
9307 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
9308 surface_desc.dwZBufferBitDepth = 16;
9309 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
9310 if (FAILED(hr))
9312 skip("Could not create Z buffer, skipping Z buffer restore test.\n");
9314 else
9316 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
9317 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9320 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9321 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9322 hr = IDirectDrawSurface_IsLost(surface);
9323 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9324 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
9325 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9326 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9327 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9328 if (vidmem_surface)
9330 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9331 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9334 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
9335 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9336 hr = IDirectDrawSurface_IsLost(surface);
9337 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9338 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
9339 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
9340 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9341 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9342 if (vidmem_surface)
9344 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9345 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9348 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
9349 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9350 hr = IDirectDrawSurface_IsLost(surface);
9351 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9352 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
9353 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
9354 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9355 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9356 if (vidmem_surface)
9358 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9359 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9362 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
9363 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9364 hr = IDirectDrawSurface_IsLost(surface);
9365 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9366 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
9367 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
9368 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9369 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9370 if (vidmem_surface)
9372 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9373 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9376 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
9377 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9378 hr = IDirectDrawSurface_IsLost(surface);
9379 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9380 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
9381 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
9382 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9383 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9384 if (vidmem_surface)
9386 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9387 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9390 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9391 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9392 hr = IDirectDrawSurface_IsLost(surface);
9393 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9394 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
9395 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9396 hr = IDirectDrawSurface_IsLost(sysmem_surface);
9397 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9398 if (vidmem_surface)
9400 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9401 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9404 memset(&caps, 0, sizeof(caps));
9405 caps.dwCaps = DDSCAPS_FLIP;
9407 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &back_buffer);
9408 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9409 ok(back_buffer != surface, "Got the same surface.\n");
9410 hr = IDirectDrawSurface_Restore(surface);
9411 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9412 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &back_buffer);
9413 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9414 hr = IDirectDrawSurface_IsLost(back_buffer);
9415 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9416 IDirectDrawSurface_Release(back_buffer);
9418 hr = IDirectDrawSurface_GetAttachedSurface(back_buffer, &caps, &back_buffer2);
9419 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9420 ok(back_buffer2 != back_buffer, "Got the same surface.\n");
9421 ok(back_buffer2 != surface, "Got the same surface.\n");
9422 hr = IDirectDrawSurface_IsLost(back_buffer2);
9423 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9424 IDirectDrawSurface_Release(back_buffer2);
9426 if (ds)
9428 hr = IDirectDrawSurface_IsLost(ds);
9429 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
9430 hr = IDirectDrawSurface_Restore(ds);
9431 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9432 hr = IDirectDrawSurface_IsLost(ds);
9433 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
9434 IDirectDrawSurface_Release(ds);
9437 if (vidmem_surface)
9438 IDirectDrawSurface_Release(vidmem_surface);
9439 IDirectDrawSurface_Release(sysmem_surface);
9440 IDirectDrawSurface_Release(surface);
9441 refcount = IDirectDraw2_Release(ddraw);
9442 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
9443 DestroyWindow(window2);
9444 DestroyWindow(window1);
9447 static void test_surface_desc_lock(void)
9449 IDirectDrawSurface *surface;
9450 DDSURFACEDESC surface_desc;
9451 IDirectDraw2 *ddraw;
9452 ULONG refcount;
9453 HWND window;
9454 HRESULT hr;
9456 window = create_window();
9457 ddraw = create_ddraw();
9458 ok(!!ddraw, "Failed to create a ddraw object.\n");
9459 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9460 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
9462 memset(&surface_desc, 0, sizeof(surface_desc));
9463 surface_desc.dwSize = sizeof(surface_desc);
9464 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
9465 surface_desc.dwWidth = 16;
9466 surface_desc.dwHeight = 16;
9467 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9468 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9469 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9471 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9472 surface_desc.dwSize = sizeof(surface_desc);
9473 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
9474 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
9475 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9477 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9478 surface_desc.dwSize = sizeof(surface_desc);
9479 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, 0, NULL);
9480 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
9481 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9482 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9483 surface_desc.dwSize = sizeof(surface_desc);
9484 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
9485 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
9486 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9487 hr = IDirectDrawSurface_Unlock(surface, NULL);
9488 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
9490 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9491 surface_desc.dwSize = sizeof(surface_desc);
9492 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
9493 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
9494 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9496 IDirectDrawSurface_Release(surface);
9497 refcount = IDirectDraw2_Release(ddraw);
9498 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
9499 DestroyWindow(window);
9502 static void test_texturemapblend(void)
9504 HRESULT hr;
9505 DDSURFACEDESC ddsd;
9506 DDBLTFX fx;
9507 static RECT rect = {0, 0, 64, 128};
9508 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9509 DDCOLORKEY ckey;
9510 IDirectDrawSurface *surface, *rt;
9511 IDirect3DTexture2 *texture;
9512 D3DTEXTUREHANDLE texture_handle;
9513 unsigned int color;
9514 HWND window;
9515 IDirectDraw2 *ddraw;
9516 IDirect3DDevice2 *device;
9517 IDirect3DMaterial2 *material;
9518 IDirect3DViewport2 *viewport;
9519 ULONG ref;
9521 static D3DTLVERTEX test1_quads[] =
9523 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {0.0f}},
9524 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {1.0f}},
9525 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {0.0f}},
9526 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {1.0f}},
9527 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {0.0f}},
9528 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {1.0f}},
9529 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {0.0f}},
9530 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {1.0f}},
9532 test2_quads[] =
9534 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {0.0f}},
9535 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {1.0f}},
9536 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {0.0f}},
9537 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {1.0f}},
9538 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {0.0f}},
9539 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {1.0f}},
9540 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {0.0f}},
9541 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {1.0f}},
9544 window = create_window();
9545 ddraw = create_ddraw();
9546 ok(!!ddraw, "Failed to create a ddraw object.\n");
9547 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
9549 skip("Failed to create a 3D device, skipping test.\n");
9550 DestroyWindow(window);
9551 IDirectDraw2_Release(ddraw);
9552 return;
9555 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
9556 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
9558 material = create_diffuse_material(device, 0.0f, 0.0f, 0.0f, 1.0f);
9559 viewport = create_viewport(device, 0, 0, 640, 480);
9560 viewport_set_background(device, viewport, material);
9561 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
9562 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
9564 /* Test alpha with DDPF_ALPHAPIXELS texture - should be taken from texture alpha channel.
9566 * The vertex alpha is completely ignored in this case, so case 1 and 2 combined are not
9567 * a D3DTOP_MODULATE with texture alpha = 0xff in case 2 (no alpha in texture). */
9568 memset(&ddsd, 0, sizeof(ddsd));
9569 ddsd.dwSize = sizeof(ddsd);
9570 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9571 ddsd.dwHeight = 128;
9572 ddsd.dwWidth = 128;
9573 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9574 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
9575 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9576 ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
9577 ddsd.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
9578 ddsd.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
9579 ddsd.ddpfPixelFormat.dwBBitMask = 0x000000ff;
9580 ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
9581 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
9582 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9584 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9585 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
9586 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
9587 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#lx.\n", hr);
9588 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
9589 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
9591 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9592 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
9594 memset(&fx, 0, sizeof(fx));
9595 fx.dwSize = sizeof(fx);
9596 fx.dwFillColor = 0xff0000ff;
9597 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9598 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
9599 fx.dwFillColor = 0x800000ff;
9600 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9601 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
9603 /* Note that the ddraw1 version of this test runs tests 1-3 with D3DRENDERSTATE_COLORKEYENABLE
9604 * enabled, whereas this version only runs test 4 with color keying on. Because no color key
9605 * is set on the texture this should not result in different behavior. */
9606 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
9607 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
9608 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9609 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
9610 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
9611 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
9612 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
9613 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
9614 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
9615 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
9616 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
9617 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
9619 hr = IDirect3DDevice2_BeginScene(device);
9620 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
9621 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[0], 4, 0);
9622 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
9623 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[4], 4, 0);
9624 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
9625 hr = IDirect3DDevice2_EndScene(device);
9626 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
9628 color = get_surface_color(rt, 5, 5);
9629 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9630 color = get_surface_color(rt, 400, 5);
9631 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9632 color = get_surface_color(rt, 5, 245);
9633 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9634 color = get_surface_color(rt, 400, 245);
9635 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9637 IDirect3DTexture2_Release(texture);
9638 ref = IDirectDrawSurface_Release(surface);
9639 ok(!ref, "Unexpected refcount %lu.\n", ref);
9641 /* Test alpha with texture that has no alpha channel - alpha should be taken from diffuse vertex color. */
9642 memset(&ddsd, 0, sizeof(ddsd));
9643 ddsd.dwSize = sizeof(ddsd);
9644 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9645 ddsd.dwHeight = 128;
9646 ddsd.dwWidth = 128;
9647 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9648 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
9649 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
9650 ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
9651 ddsd.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
9652 ddsd.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
9653 ddsd.ddpfPixelFormat.dwBBitMask = 0x000000ff;
9655 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
9656 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9658 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9659 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
9660 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
9661 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#lx.\n", hr);
9662 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
9663 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
9665 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9666 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
9668 fx.dwFillColor = 0xff0000ff;
9669 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9670 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
9671 fx.dwFillColor = 0x800000ff;
9672 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9673 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
9675 hr = IDirect3DDevice2_BeginScene(device);
9676 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
9677 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[0], 4, 0);
9678 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
9679 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[4], 4, 0);
9680 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
9681 hr = IDirect3DDevice2_EndScene(device);
9682 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
9684 color = get_surface_color(rt, 5, 5);
9685 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9686 color = get_surface_color(rt, 400, 5);
9687 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9688 color = get_surface_color(rt, 5, 245);
9689 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9690 color = get_surface_color(rt, 400, 245);
9691 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9693 IDirect3DTexture2_Release(texture);
9694 ref = IDirectDrawSurface_Release(surface);
9695 ok(!ref, "Unexpected refcount %lu.\n", ref);
9697 /* Test RGB - should multiply color components from diffuse vertex color and texture. */
9698 memset(&ddsd, 0, sizeof(ddsd));
9699 ddsd.dwSize = sizeof(ddsd);
9700 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9701 ddsd.dwHeight = 128;
9702 ddsd.dwWidth = 128;
9703 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9704 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
9705 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9706 ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
9707 ddsd.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
9708 ddsd.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
9709 ddsd.ddpfPixelFormat.dwBBitMask = 0x000000ff;
9710 ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
9711 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
9712 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9714 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9715 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
9716 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
9717 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#lx.\n", hr);
9718 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
9719 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
9721 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9722 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
9724 fx.dwFillColor = 0x00ffffff;
9725 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9726 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
9727 fx.dwFillColor = 0x00ffff80;
9728 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9729 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
9731 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
9732 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
9734 hr = IDirect3DDevice2_BeginScene(device);
9735 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
9736 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test2_quads[0], 4, 0);
9737 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
9738 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test2_quads[4], 4, 0);
9739 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
9740 hr = IDirect3DDevice2_EndScene(device);
9741 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
9743 color = get_surface_color(rt, 5, 5);
9744 ok(compare_color(color, 0x00ff0040, 2), "Got unexpected color 0x%08x.\n", color);
9745 color = get_surface_color(rt, 400, 5);
9746 ok(compare_color(color, 0x00ff0080, 2), "Got unexpected color 0x%08x.\n", color);
9747 color = get_surface_color(rt, 5, 245);
9748 ok(compare_color(color, 0x00800080, 2), "Got unexpected color 0x%08x.\n", color);
9749 color = get_surface_color(rt, 400, 245);
9750 ok(compare_color(color, 0x008000ff, 2), "Got unexpected color 0x%08x.\n", color);
9752 IDirect3DTexture2_Release(texture);
9753 ref = IDirectDrawSurface_Release(surface);
9754 ok(!ref, "Unexpected refcount %lu.\n", ref);
9756 /* Test alpha again, now with color keyed texture (colorkey emulation in wine can interfere). */
9757 memset(&ddsd, 0, sizeof(ddsd));
9758 ddsd.dwSize = sizeof(ddsd);
9759 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9760 ddsd.dwHeight = 128;
9761 ddsd.dwWidth = 128;
9762 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9763 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
9764 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
9765 ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
9766 ddsd.ddpfPixelFormat.dwRBitMask = 0xf800;
9767 ddsd.ddpfPixelFormat.dwGBitMask = 0x07e0;
9768 ddsd.ddpfPixelFormat.dwBBitMask = 0x001f;
9770 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
9771 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9773 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9774 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
9775 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
9776 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#lx.\n", hr);
9777 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
9778 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
9780 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9781 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
9783 fx.dwFillColor = 0xf800;
9784 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9785 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
9786 fx.dwFillColor = 0x001f;
9787 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9788 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
9790 ckey.dwColorSpaceLowValue = 0x001f;
9791 ckey.dwColorSpaceHighValue = 0x001f;
9792 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9793 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
9795 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
9796 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
9797 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
9798 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
9800 hr = IDirect3DDevice2_BeginScene(device);
9801 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
9802 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[0], 4, 0);
9803 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
9804 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[4], 4, 0);
9805 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
9806 hr = IDirect3DDevice2_EndScene(device);
9807 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
9809 color = get_surface_color(rt, 5, 5);
9810 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
9811 color = get_surface_color(rt, 400, 5);
9812 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
9813 color = get_surface_color(rt, 5, 245);
9814 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
9815 color = get_surface_color(rt, 400, 245);
9816 ok(compare_color(color, 0x00800000, 2), "Got unexpected color 0x%08x.\n", color);
9818 IDirect3DTexture2_Release(texture);
9819 ref = IDirectDrawSurface_Release(surface);
9820 ok(!ref, "Unexpected refcount %lu.\n", ref);
9822 destroy_viewport(device, viewport);
9823 ref = IDirect3DMaterial2_Release(material);
9824 ok(!ref, "Unexpected refcount %lu.\n", ref);
9825 IDirectDrawSurface_Release(rt);
9826 IDirect3DDevice2_Release(device);
9827 ref = IDirectDraw2_Release(ddraw);
9828 ok(!ref, "Unexpected refcount %lu.\n", ref);
9829 DestroyWindow(window);
9832 static void test_viewport_clear_rect(void)
9834 HRESULT hr;
9835 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9836 static D3DRECT clear_rect2 = {{90}, {90}, {110}, {110}};
9837 IDirectDrawSurface *rt;
9838 unsigned int color;
9839 HWND window;
9840 IDirectDraw2 *ddraw;
9841 IDirect3DDevice2 *device;
9842 IDirect3DMaterial2 *red, *green;
9843 IDirect3DViewport2 *viewport, *viewport2;
9844 ULONG ref;
9846 window = create_window();
9847 ddraw = create_ddraw();
9848 ok(!!ddraw, "Failed to create a ddraw object.\n");
9849 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
9851 skip("Failed to create a 3D device, skipping test.\n");
9852 DestroyWindow(window);
9853 IDirectDraw2_Release(ddraw);
9854 return;
9857 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
9858 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
9860 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
9861 viewport = create_viewport(device, 0, 0, 640, 480);
9862 viewport_set_background(device, viewport, red);
9863 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9864 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
9866 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
9867 viewport2 = create_viewport(device, 100, 100, 20, 20);
9868 viewport_set_background(device, viewport2, green);
9869 hr = IDirect3DViewport2_Clear(viewport2, 1, &clear_rect2, D3DCLEAR_TARGET);
9870 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
9872 color = get_surface_color(rt, 85, 85); /* Outside both. */
9873 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
9874 color = get_surface_color(rt, 95, 95); /* Outside vp, inside rect. */
9875 /* AMD GPUs ignore the viewport dimensions and only care about the rectangle. */
9876 ok(compare_color(color, 0x00ff0000, 1) || broken(compare_color(color, 0x0000ff00, 1)),
9877 "Got unexpected color 0x%08x.\n", color);
9878 color = get_surface_color(rt, 105, 105); /* Inside both. */
9879 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
9880 color = get_surface_color(rt, 115, 115); /* Inside vp, outside rect. */
9881 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
9882 color = get_surface_color(rt, 125, 125); /* Outside both. */
9883 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
9885 destroy_viewport(device, viewport2);
9886 destroy_material(green);
9887 destroy_viewport(device, viewport);
9888 destroy_material(red);
9889 IDirectDrawSurface_Release(rt);
9890 IDirect3DDevice2_Release(device);
9891 ref = IDirectDraw2_Release(ddraw);
9892 ok(!ref, "Unexpected refcount %lu.\n", ref);
9893 DestroyWindow(window);
9896 static void test_color_fill(void)
9898 HRESULT hr;
9899 IDirect3DDevice2 *device;
9900 IDirectDraw2 *ddraw;
9901 IDirectDrawSurface *surface, *surface2;
9902 DDSURFACEDESC surface_desc;
9903 unsigned int i, *color;
9904 ULONG refcount;
9905 BOOL is_warp;
9906 HWND window;
9907 DDBLTFX fx;
9908 RECT rect = {5, 5, 7, 7};
9909 DWORD num_fourcc_codes, *fourcc_codes;
9910 DDCAPS hal_caps;
9911 BOOL support_uyvy = FALSE, support_yuy2 = FALSE;
9912 static const struct
9914 DWORD caps;
9915 HRESULT colorfill_hr, depthfill_hr;
9916 BOOL rop_success;
9917 const char *name;
9918 unsigned int result;
9919 BOOL check_result;
9920 DDPIXELFORMAT format;
9922 tests[] =
9925 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
9926 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
9928 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9929 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9933 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
9934 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
9936 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9937 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9941 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
9942 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
9944 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9945 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9949 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
9950 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
9952 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9953 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9957 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY,
9958 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0xdeadbeef, TRUE,
9959 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9962 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
9963 * different afterwards. DX9+ GPUs set one of the two luminance values
9964 * in each block, but AMD and Nvidia GPUs disagree on which luminance
9965 * value they set. r200 (dx8) just sets the entire block to the clear
9966 * value. */
9967 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
9968 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
9970 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9971 {0}, {0}, {0}, {0}, {0}
9975 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
9976 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
9978 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9979 {0}, {0}, {0}, {0}, {0}
9983 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
9984 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
9986 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9987 {0}, {0}, {0}, {0}, {0}
9991 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
9992 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
9994 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9995 {0}, {0}, {0}, {0}, {0}
9999 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
10000 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
10002 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
10003 {0}, {0}, {0}, {0}, {0}
10007 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
10008 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
10010 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
10011 {0}, {0}, {0}, {0}, {0}
10015 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
10016 * surface works, presumably because it is handled by the runtime instead of
10017 * the driver. */
10018 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
10019 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
10021 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
10022 {8}, {0}, {0}, {0}, {0}
10026 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
10027 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
10029 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
10030 {8}, {0}, {0}, {0}, {0}
10034 static const struct
10036 DWORD rop;
10037 const char *name;
10038 HRESULT hr;
10040 rops[] =
10042 {SRCCOPY, "SRCCOPY", DD_OK},
10043 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
10044 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
10045 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
10046 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
10047 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
10048 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
10049 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
10050 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
10051 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
10052 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
10053 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
10054 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
10055 {BLACKNESS, "BLACKNESS", DD_OK},
10056 {WHITENESS, "WHITENESS", DD_OK},
10057 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
10060 window = create_window();
10061 ddraw = create_ddraw();
10062 ok(!!ddraw, "Failed to create a ddraw object.\n");
10063 is_warp = ddraw_is_warp(ddraw);
10064 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
10066 skip("Failed to create a 3D device, skipping test.\n");
10067 DestroyWindow(window);
10068 IDirectDraw2_Release(ddraw);
10069 return;
10072 hr = IDirectDraw2_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
10073 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
10074 fourcc_codes = calloc(num_fourcc_codes, sizeof(*fourcc_codes));
10075 if (!fourcc_codes)
10076 goto done;
10077 hr = IDirectDraw2_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
10078 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
10079 for (i = 0; i < num_fourcc_codes; i++)
10081 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
10082 support_yuy2 = TRUE;
10083 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
10084 support_uyvy = TRUE;
10086 free(fourcc_codes);
10088 memset(&hal_caps, 0, sizeof(hal_caps));
10089 hal_caps.dwSize = sizeof(hal_caps);
10090 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
10091 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
10093 if ((!support_yuy2 && !support_uyvy) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
10094 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
10096 for (i = 0; i < ARRAY_SIZE(tests); i++)
10098 DWORD expected_broken = tests[i].result;
10099 unsigned int mask = 0xffffffffu;
10101 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
10102 memset(&fx, 0, sizeof(fx));
10103 fx.dwSize = sizeof(fx);
10104 fx.dwFillColor = 0xdeadbeef;
10106 memset(&surface_desc, 0, sizeof(surface_desc));
10107 surface_desc.dwSize = sizeof(surface_desc);
10108 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10109 surface_desc.dwWidth = 64;
10110 surface_desc.dwHeight = 64;
10111 surface_desc.ddpfPixelFormat = tests[i].format;
10112 surface_desc.ddsCaps.dwCaps = tests[i].caps;
10114 if (tests[i].caps & DDSCAPS_TEXTURE)
10116 struct format_support_check check = {&tests[i].format, FALSE};
10117 hr = IDirect3DDevice2_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
10118 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
10119 if (!check.supported)
10120 continue;
10123 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !support_yuy2)
10124 continue;
10125 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !support_uyvy)
10126 continue;
10127 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
10128 continue;
10130 if (tests[i].caps & DDSCAPS_ZBUFFER)
10132 surface_desc.dwFlags &= ~DDSD_PIXELFORMAT;
10133 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
10134 surface_desc.dwZBufferBitDepth = get_device_z_depth(device);
10135 mask >>= (32 - surface_desc.dwZBufferBitDepth);
10136 /* Some drivers seem to convert depth values incorrectly or not at
10137 * all. Affects at least AMD PALM, 8.17.10.1247. */
10138 if (tests[i].caps & DDSCAPS_VIDEOMEMORY)
10140 DWORD expected;
10141 float f, g;
10143 expected = tests[i].result & mask;
10144 f = ceilf(logf(expected + 1.0f) / logf(2.0f));
10145 g = (f + 1.0f) / 2.0f;
10146 g -= (int)g;
10147 expected_broken = (expected / exp2f(f) - g) * 256;
10148 expected_broken *= 0x01010101;
10152 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10153 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx, surface %s.\n", hr, tests[i].name);
10155 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10156 todo_wine_if (tests[i].format.dwFourCC)
10157 ok(hr == tests[i].colorfill_hr, "Blt returned %#lx, expected %#lx, surface %s.\n",
10158 hr, tests[i].colorfill_hr, tests[i].name);
10160 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10161 todo_wine_if (tests[i].format.dwFourCC)
10162 ok(hr == tests[i].colorfill_hr, "Blt returned %#lx, expected %#lx, surface %s.\n",
10163 hr, tests[i].colorfill_hr, tests[i].name);
10165 if (SUCCEEDED(hr) && tests[i].check_result)
10167 memset(&surface_desc, 0, sizeof(surface_desc));
10168 surface_desc.dwSize = sizeof(surface_desc);
10169 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10170 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
10171 color = surface_desc.lpSurface;
10172 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
10173 *color, tests[i].result, tests[i].name);
10174 hr = IDirectDrawSurface_Unlock(surface, NULL);
10175 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
10178 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10179 ok(hr == tests[i].depthfill_hr, "Blt returned %#lx, expected %#lx, surface %s.\n",
10180 hr, tests[i].depthfill_hr, tests[i].name);
10181 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10182 ok(hr == tests[i].depthfill_hr, "Blt returned %#lx, expected %#lx, surface %s.\n",
10183 hr, tests[i].depthfill_hr, tests[i].name);
10185 if (SUCCEEDED(hr) && tests[i].check_result)
10187 memset(&surface_desc, 0, sizeof(surface_desc));
10188 surface_desc.dwSize = sizeof(surface_desc);
10189 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10190 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
10191 color = surface_desc.lpSurface;
10192 todo_wine_if(tests[i].caps & DDSCAPS_VIDEOMEMORY && surface_desc.dwZBufferBitDepth != 16)
10193 ok((*color & mask) == (tests[i].result & mask) || broken((*color & mask) == (expected_broken & mask))
10194 || broken(is_warp && (*color & mask) == (~0u & mask)) /* Windows 8+ testbot. */,
10195 "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
10196 *color & mask, tests[i].result & mask, tests[i].name);
10197 hr = IDirectDrawSurface_Unlock(surface, NULL);
10198 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
10201 fx.dwFillColor = 0xdeadbeef;
10202 fx.dwROP = BLACKNESS;
10203 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10204 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#lx, expected %s, surface %s.\n",
10205 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
10206 ok(fx.dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08lx, surface %s\n",
10207 fx.dwFillColor, tests[i].name);
10209 if (SUCCEEDED(hr) && tests[i].check_result)
10211 memset(&surface_desc, 0, sizeof(surface_desc));
10212 surface_desc.dwSize = sizeof(surface_desc);
10213 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10214 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
10215 color = surface_desc.lpSurface;
10216 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
10217 *color, tests[i].name);
10218 hr = IDirectDrawSurface_Unlock(surface, NULL);
10219 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
10222 fx.dwROP = WHITENESS;
10223 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10224 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#lx, expected %s, surface %s.\n",
10225 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
10226 ok(fx.dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08lx, surface %s\n",
10227 fx.dwFillColor, tests[i].name);
10229 if (SUCCEEDED(hr) && tests[i].check_result)
10231 memset(&surface_desc, 0, sizeof(surface_desc));
10232 surface_desc.dwSize = sizeof(surface_desc);
10233 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10234 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
10235 color = surface_desc.lpSurface;
10236 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
10237 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
10238 *color, tests[i].name);
10239 hr = IDirectDrawSurface_Unlock(surface, NULL);
10240 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
10243 IDirectDrawSurface_Release(surface);
10246 memset(&fx, 0, sizeof(fx));
10247 fx.dwSize = sizeof(fx);
10248 fx.dwFillColor = 0xdeadbeef;
10249 fx.dwROP = WHITENESS;
10251 memset(&surface_desc, 0, sizeof(surface_desc));
10252 surface_desc.dwSize = sizeof(surface_desc);
10253 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10254 surface_desc.dwWidth = 64;
10255 surface_desc.dwHeight = 64;
10256 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
10257 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
10258 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
10259 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
10260 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
10261 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
10262 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10263 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10264 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10265 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10266 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10268 /* No DDBLTFX. */
10269 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
10270 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10271 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
10272 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10274 /* Unused source rectangle. */
10275 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10276 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
10277 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10278 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
10280 /* Unused source surface. */
10281 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10282 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10283 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10284 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
10285 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10286 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10287 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10288 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
10290 /* Inverted destination or source rectangle. */
10291 SetRect(&rect, 5, 7, 7, 5);
10292 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10293 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
10294 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10295 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
10296 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10297 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10298 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10299 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10300 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10301 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
10303 /* Negative rectangle. */
10304 SetRect(&rect, -1, -1, 5, 5);
10305 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10306 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
10307 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10308 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
10309 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10310 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10311 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10312 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10313 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10314 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
10316 /* Out of bounds rectangle. */
10317 SetRect(&rect, 0, 0, 65, 65);
10318 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10319 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
10320 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10321 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
10323 /* Combine multiple flags. */
10324 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10325 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
10326 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10327 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10328 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10329 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10331 for (i = 0; i < ARRAY_SIZE(rops); i++)
10333 fx.dwROP = rops[i].rop;
10334 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10335 ok(hr == rops[i].hr, "Got unexpected hr %#lx for rop %s.\n", hr, rops[i].name);
10338 IDirectDrawSurface_Release(surface2);
10339 IDirectDrawSurface_Release(surface);
10341 memset(&surface_desc, 0, sizeof(surface_desc));
10342 surface_desc.dwSize = sizeof(surface_desc);
10343 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
10344 surface_desc.dwWidth = 64;
10345 surface_desc.dwHeight = 64;
10346 surface_desc.dwZBufferBitDepth = get_device_z_depth(device);
10347 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
10348 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10349 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10350 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10351 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10353 /* No DDBLTFX. */
10354 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
10355 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10357 /* Unused source rectangle. */
10358 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10359 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
10361 /* Unused source surface. */
10362 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10363 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10364 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10365 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10367 /* Inverted destination or source rectangle. */
10368 SetRect(&rect, 5, 7, 7, 5);
10369 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10370 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
10371 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10372 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
10373 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10374 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10375 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10376 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10378 /* Negative rectangle. */
10379 SetRect(&rect, -1, -1, 5, 5);
10380 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10381 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
10382 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10383 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
10384 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10385 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10386 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10387 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10389 /* Out of bounds rectangle. */
10390 SetRect(&rect, 0, 0, 65, 65);
10391 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10392 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
10394 /* Combine multiple flags. */
10395 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10396 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
10398 IDirectDrawSurface_Release(surface2);
10399 IDirectDrawSurface_Release(surface);
10401 done:
10402 IDirect3DDevice2_Release(device);
10403 refcount = IDirectDraw2_Release(ddraw);
10404 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
10405 DestroyWindow(window);
10408 static void test_colorkey_precision(void)
10410 static D3DLVERTEX quad[] =
10412 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xff000000}, {0}, {0.0f}, {0.0f}},
10413 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff000000}, {0}, {0.0f}, {1.0f}},
10414 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff000000}, {0}, {1.0f}, {0.0f}},
10415 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xff000000}, {0}, {1.0f}, {1.0f}},
10417 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10418 unsigned int data[4] = {0}, color_mask, color, t, c;
10419 IDirect3DDevice2 *device;
10420 IDirectDraw2 *ddraw;
10421 IDirectDrawSurface *rt;
10422 IDirect3DViewport2 *viewport;
10423 HWND window;
10424 HRESULT hr;
10425 IDirectDrawSurface *src, *dst, *texture;
10426 D3DTEXTUREHANDLE handle;
10427 IDirect3DTexture2 *d3d_texture;
10428 IDirect3DMaterial2 *green;
10429 DDSURFACEDESC surface_desc, lock_desc;
10430 ULONG refcount;
10431 DDCOLORKEY ckey;
10432 DDBLTFX fx;
10433 BOOL is_nvidia, is_warp;
10434 static const struct
10436 unsigned int max, shift, bpp, clear;
10437 const char *name;
10438 BOOL skip_nv;
10439 DDPIXELFORMAT fmt;
10441 tests[] =
10444 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
10446 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10447 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
10452 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
10454 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10455 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10460 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
10462 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10463 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10468 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
10470 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10471 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
10476 window = create_window();
10477 ddraw = create_ddraw();
10478 ok(!!ddraw, "Failed to create a ddraw object.\n");
10479 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
10481 skip("Failed to create a 3D device, skipping test.\n");
10482 DestroyWindow(window);
10483 IDirectDraw2_Release(ddraw);
10484 return;
10486 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
10487 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
10489 is_nvidia = ddraw_is_nvidia(ddraw);
10490 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
10491 * (color key doesn't match although the values are equal), and a false
10492 * positive when the color key is 0 and the texture contains the value 1.
10493 * I don't want to mark this broken unconditionally since this would
10494 * essentially disable the test on Windows. Also on random occasions
10495 * 254 == 255 and 255 != 255.*/
10496 is_warp = ddraw_is_warp(ddraw);
10498 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
10499 viewport = create_viewport(device, 0, 0, 640, 480);
10500 viewport_set_background(device, viewport, green);
10501 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
10502 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#lx.\n", hr);
10504 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10505 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#lx.\n", hr);
10506 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
10507 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#lx.\n", hr);
10508 /* There's no way to ignore the texture color in d3d2, so multiply the texture color
10509 * with a black vertex color. */
10510 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATEALPHA);
10511 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
10513 memset(&fx, 0, sizeof(fx));
10514 fx.dwSize = sizeof(fx);
10515 memset(&lock_desc, 0, sizeof(lock_desc));
10516 lock_desc.dwSize = sizeof(lock_desc);
10518 for (t = 0; t < ARRAY_SIZE(tests); ++t)
10520 if (is_nvidia && tests[t].skip_nv)
10522 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
10523 continue;
10526 memset(&surface_desc, 0, sizeof(surface_desc));
10527 surface_desc.dwSize = sizeof(surface_desc);
10528 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10529 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10530 surface_desc.dwWidth = 4;
10531 surface_desc.dwHeight = 1;
10532 surface_desc.ddpfPixelFormat = tests[t].fmt;
10533 /* Windows XP (at least with the r200 driver, other drivers untested) produces
10534 * garbage when doing color keyed texture->texture blits. */
10535 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src, NULL);
10536 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10537 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst, NULL);
10538 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10540 fx.dwFillColor = tests[t].clear;
10541 /* On the w8 testbot (WARP driver) the blit result has different values in the
10542 * X channel. */
10543 color_mask = tests[t].fmt.dwRBitMask
10544 | tests[t].fmt.dwGBitMask
10545 | tests[t].fmt.dwBBitMask;
10547 for (c = 0; c <= tests[t].max; ++c)
10549 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
10550 * texture after it has been set once... */
10551 surface_desc.dwFlags |= DDSD_CKSRCBLT;
10552 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10553 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
10554 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
10555 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &texture, NULL);
10556 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10558 hr = IDirectDrawSurface4_QueryInterface(texture, &IID_IDirect3DTexture2, (void **)&d3d_texture);
10559 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
10560 hr = IDirect3DTexture2_GetHandle(d3d_texture, device, &handle);
10561 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#lx.\n", hr);
10562 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, handle);
10563 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#lx.\n", hr);
10564 IDirect3DTexture2_Release(d3d_texture);
10566 hr = IDirectDrawSurface_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10567 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#lx.\n", hr);
10569 hr = IDirectDrawSurface_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10570 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
10571 switch (tests[t].bpp)
10573 case 4:
10574 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10575 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10576 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10577 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
10578 break;
10580 case 2:
10581 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10582 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10583 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10584 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
10585 break;
10587 hr = IDirectDrawSurface_Unlock(src, 0);
10588 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
10589 hr = IDirectDrawSurface_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
10590 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
10592 ckey.dwColorSpaceLowValue = c << tests[t].shift;
10593 ckey.dwColorSpaceHighValue = c << tests[t].shift;
10594 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
10595 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
10597 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
10598 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
10600 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
10601 hr = IDirectDrawSurface_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10602 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
10603 switch (tests[t].bpp)
10605 case 4:
10606 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
10607 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
10608 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
10609 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
10610 break;
10612 case 2:
10613 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
10614 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
10615 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
10616 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
10617 break;
10619 hr = IDirectDrawSurface_Unlock(dst, 0);
10620 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
10622 if (!c)
10624 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10625 tests[t].clear, data[0], tests[t].name, c);
10627 if (data[3] == tests[t].clear)
10629 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
10630 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
10631 * even when a different surface is used. The blit itself doesn't draw anything,
10632 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
10633 * never be masked out by the key.
10635 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
10636 * test is disabled entirely.
10638 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
10639 * terrible on WARP. */
10640 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
10641 IDirectDrawSurface_Release(texture);
10642 IDirectDrawSurface_Release(src);
10643 IDirectDrawSurface_Release(dst);
10644 goto done;
10647 else
10648 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10649 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
10651 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10652 tests[t].clear, data[1], tests[t].name, c);
10654 if (c == tests[t].max)
10655 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10656 tests[t].clear, data[2], tests[t].name, c);
10657 else
10658 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10659 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
10661 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
10662 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
10664 hr = IDirect3DDevice2_BeginScene(device);
10665 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
10666 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
10667 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
10668 hr = IDirect3DDevice2_EndScene(device);
10669 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
10671 color = get_surface_color(rt, 80, 240);
10672 if (!c)
10673 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10674 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10675 color, tests[t].name, c);
10676 else
10677 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
10678 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10679 color, tests[t].name, c);
10681 color = get_surface_color(rt, 240, 240);
10682 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10683 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10684 color, tests[t].name, c);
10686 color = get_surface_color(rt, 400, 240);
10687 if (c == tests[t].max)
10688 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10689 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10690 color, tests[t].name, c);
10691 else
10692 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
10693 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10694 color, tests[t].name, c);
10696 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
10697 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#lx.\n", hr);
10698 IDirectDrawSurface_Release(texture);
10700 IDirectDrawSurface_Release(src);
10701 IDirectDrawSurface_Release(dst);
10703 done:
10705 destroy_viewport(device, viewport);
10706 destroy_material(green);
10707 IDirectDrawSurface_Release(rt);
10708 IDirect3DDevice2_Release(device);
10709 refcount = IDirectDraw2_Release(ddraw);
10710 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
10711 DestroyWindow(window);
10714 static void test_range_colorkey(void)
10716 IDirectDraw2 *ddraw;
10717 HWND window;
10718 HRESULT hr;
10719 IDirectDrawSurface *surface;
10720 DDSURFACEDESC surface_desc;
10721 ULONG refcount;
10722 DDCOLORKEY ckey;
10724 window = create_window();
10725 ddraw = create_ddraw();
10726 ok(!!ddraw, "Failed to create a ddraw object.\n");
10727 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10728 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
10730 memset(&surface_desc, 0, sizeof(surface_desc));
10731 surface_desc.dwSize = sizeof(surface_desc);
10732 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
10733 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10734 surface_desc.dwWidth = 1;
10735 surface_desc.dwHeight = 1;
10736 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
10737 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
10738 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
10739 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
10740 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
10741 surface_desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0x00000000;
10743 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
10744 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10745 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10746 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10747 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
10749 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10750 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10751 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10752 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
10754 /* Same for DDSCAPS_OFFSCREENPLAIN. */
10755 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10756 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10757 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10758 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10759 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
10761 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10762 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10763 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10764 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
10766 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10767 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10768 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10769 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10771 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
10772 ckey.dwColorSpaceLowValue = 0x00000000;
10773 ckey.dwColorSpaceHighValue = 0x00000001;
10774 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10775 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
10777 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10778 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
10779 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
10780 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
10782 ckey.dwColorSpaceLowValue = 0x00000001;
10783 ckey.dwColorSpaceHighValue = 0x00000000;
10784 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10785 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
10787 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10788 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
10789 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
10790 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
10792 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
10793 ckey.dwColorSpaceLowValue = 0x00000000;
10794 ckey.dwColorSpaceHighValue = 0x00000000;
10795 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10796 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
10798 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
10799 ckey.dwColorSpaceLowValue = 0x00000001;
10800 ckey.dwColorSpaceHighValue = 0x00000000;
10801 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10802 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
10803 ckey.dwColorSpaceLowValue = 0x00000000;
10804 ckey.dwColorSpaceHighValue = 0x00000001;
10805 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10806 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
10807 /* Range destination keys don't work either. */
10808 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
10809 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
10811 /* Just to show it's not because of A, R, and G having equal values. */
10812 ckey.dwColorSpaceLowValue = 0x00000000;
10813 ckey.dwColorSpaceHighValue = 0x01010101;
10814 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10815 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
10817 /* None of these operations modified the key. */
10818 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10819 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
10820 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
10821 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
10823 IDirectDrawSurface_Release(surface);
10824 refcount = IDirectDraw2_Release(ddraw);
10825 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
10826 DestroyWindow(window);
10829 static void test_shademode(void)
10831 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10832 unsigned int color0, color1, i, count;
10833 IDirect3DMaterial2 *background;
10834 IDirect3DViewport2 *viewport;
10835 IDirect3DDevice2 *device;
10836 IDirectDrawSurface *rt;
10837 IDirectDraw2 *ddraw;
10838 D3DLVERTEX *quad;
10839 ULONG refcount;
10840 HWND window;
10841 HRESULT hr;
10842 static D3DLVERTEX quad_strip[] =
10844 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
10845 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
10846 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
10847 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
10849 quad_list[] =
10851 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
10852 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
10853 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
10855 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
10856 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
10857 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
10859 static const struct
10861 DWORD primtype;
10862 DWORD shademode;
10863 unsigned int color0, color1;
10865 tests[] =
10867 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
10868 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10869 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10870 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10871 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
10872 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10875 window = create_window();
10876 ddraw = create_ddraw();
10877 ok(!!ddraw, "Failed to create a ddraw object.\n");
10878 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
10880 skip("Failed to create a 3D device, skipping test.\n");
10881 IDirectDraw2_Release(ddraw);
10882 DestroyWindow(window);
10883 return;
10886 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
10887 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
10889 background = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
10890 viewport = create_viewport(device, 0, 0, 640, 480);
10891 viewport_set_background(device, viewport, background);
10892 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
10893 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#lx.\n", hr);
10895 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
10896 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#lx.\n", hr);
10898 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
10899 * the color fixups we have to do for FLAT shading will be dependent on that. */
10901 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10903 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
10904 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
10906 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
10907 ok(hr == D3D_OK, "Failed to set shade mode, hr %#lx.\n", hr);
10909 hr = IDirect3DDevice2_BeginScene(device);
10910 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
10911 quad = tests[i].primtype == D3DPT_TRIANGLESTRIP ? quad_strip : quad_list;
10912 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
10913 hr = IDirect3DDevice2_DrawPrimitive(device, tests[i].primtype, D3DVT_LVERTEX, quad, count, 0);
10914 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
10915 hr = IDirect3DDevice2_EndScene(device);
10916 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
10918 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
10919 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
10921 /* For D3DSHADE_FLAT it should take the color of the first vertex of
10922 * each triangle. This requires EXT_provoking_vertex or similar
10923 * functionality being available. */
10924 /* PHONG should be the same as GOURAUD, since no hardware implements
10925 * this. */
10926 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
10927 i, color0, tests[i].color0);
10928 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
10929 i, color1, tests[i].color1);
10932 destroy_viewport(device, viewport);
10933 destroy_material(background);
10934 IDirectDrawSurface_Release(rt);
10935 refcount = IDirect3DDevice2_Release(device);
10936 ok(!refcount, "Device has %lu references left.\n", refcount);
10937 IDirectDraw2_Release(ddraw);
10938 DestroyWindow(window);
10941 static void test_lockrect_invalid(void)
10943 unsigned int i, r;
10944 IDirectDraw2 *ddraw;
10945 IDirectDrawSurface *surface1;
10946 IDirectDrawSurface2 *surface;
10947 HWND window;
10948 HRESULT hr;
10949 DDSURFACEDESC surface_desc;
10950 DDCAPS hal_caps;
10951 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
10952 static RECT valid[] =
10954 {60, 60, 68, 68},
10955 {60, 60, 60, 68},
10956 {60, 60, 68, 60},
10957 {120, 60, 128, 68},
10958 {60, 120, 68, 128},
10960 static RECT invalid[] =
10962 {68, 60, 60, 68}, /* left > right */
10963 {60, 68, 68, 60}, /* top > bottom */
10964 {-8, 60, 0, 68}, /* left < surface */
10965 {60, -8, 68, 0}, /* top < surface */
10966 {-16, 60, -8, 68}, /* right < surface */
10967 {60, -16, 68, -8}, /* bottom < surface */
10968 {60, 60, 136, 68}, /* right > surface */
10969 {60, 60, 68, 136}, /* bottom > surface */
10970 {136, 60, 144, 68}, /* left > surface */
10971 {60, 136, 68, 144}, /* top > surface */
10973 static const struct
10975 DWORD caps;
10976 const char *name;
10977 HRESULT hr;
10979 resources[] =
10981 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, "sysmem offscreenplain", DDERR_INVALIDPARAMS},
10982 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, "vidmem offscreenplain", DDERR_INVALIDPARAMS},
10983 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "sysmem texture", DDERR_INVALIDPARAMS},
10984 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "vidmem texture", DDERR_INVALIDPARAMS},
10987 window = create_window();
10988 ddraw = create_ddraw();
10989 ok(!!ddraw, "Failed to create a ddraw object.\n");
10990 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10991 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
10993 memset(&hal_caps, 0, sizeof(hal_caps));
10994 hal_caps.dwSize = sizeof(hal_caps);
10995 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
10996 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
10997 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
10999 skip("Required surface types not supported, skipping test.\n");
11000 goto done;
11003 for (r = 0; r < ARRAY_SIZE(resources); ++r)
11005 memset(&surface_desc, 0, sizeof(surface_desc));
11006 surface_desc.dwSize = sizeof(surface_desc);
11007 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11008 surface_desc.ddsCaps.dwCaps = resources[r].caps;
11009 surface_desc.dwWidth = 128;
11010 surface_desc.dwHeight = 128;
11011 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
11012 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
11013 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
11014 surface_desc.ddpfPixelFormat.dwRBitMask = 0xff0000;
11015 surface_desc.ddpfPixelFormat.dwGBitMask = 0x00ff00;
11016 surface_desc.ddpfPixelFormat.dwBBitMask = 0x0000ff;
11018 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
11019 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx, type %s.\n", hr, resources[r].name);
11020 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
11021 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface2 interface, hr %#lx.\n", hr);
11022 IDirectDrawSurface_Release(surface1);
11024 hr = IDirectDrawSurface2_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
11025 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx, type %s.\n", hr, resources[r].name);
11027 for (i = 0; i < ARRAY_SIZE(valid); ++i)
11029 RECT *rect = &valid[i];
11031 memset(&surface_desc, 0, sizeof(surface_desc));
11032 surface_desc.dwSize = sizeof(surface_desc);
11034 hr = IDirectDrawSurface2_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
11035 ok(SUCCEEDED(hr), "Lock failed (%#lx) for rect %s, type %s.\n",
11036 hr, wine_dbgstr_rect(rect), resources[r].name);
11038 hr = IDirectDrawSurface2_Unlock(surface, NULL);
11039 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
11042 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
11044 RECT *rect = &invalid[i];
11046 memset(&surface_desc, 1, sizeof(surface_desc));
11047 surface_desc.dwSize = sizeof(surface_desc);
11049 hr = IDirectDrawSurface2_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
11050 ok(hr == resources[r].hr, "Lock returned %#lx for rect %s, type %s.\n",
11051 hr, wine_dbgstr_rect(rect), resources[r].name);
11052 if (SUCCEEDED(hr))
11054 hr = IDirectDrawSurface2_Unlock(surface, NULL);
11055 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
11057 else
11058 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
11061 hr = IDirectDrawSurface2_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
11062 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#lx, type %s.\n",
11063 hr, resources[r].name);
11064 hr = IDirectDrawSurface2_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
11065 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#lx, type %s.\n",
11066 hr, resources[r].name);
11067 hr = IDirectDrawSurface2_Unlock(surface, NULL);
11068 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
11070 hr = IDirectDrawSurface2_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
11071 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#lx).\n", wine_dbgstr_rect(&valid[0]), hr);
11072 hr = IDirectDrawSurface2_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
11073 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#lx).\n",
11074 wine_dbgstr_rect(&valid[0]), hr);
11076 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
11077 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
11079 hr = IDirectDrawSurface2_Unlock(surface, NULL);
11080 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
11082 IDirectDrawSurface2_Release(surface);
11085 done:
11086 IDirectDraw2_Release(ddraw);
11087 DestroyWindow(window);
11090 static void test_yv12_overlay(void)
11092 IDirectDrawSurface *src_surface, *dst_surface;
11093 RECT rect = {13, 17, 14, 18};
11094 unsigned int offset, y;
11095 unsigned char *base;
11096 IDirectDraw2 *ddraw;
11097 DDSURFACEDESC desc;
11098 HWND window;
11099 HRESULT hr;
11101 window = create_window();
11102 ddraw = create_ddraw();
11103 ok(!!ddraw, "Failed to create a ddraw object.\n");
11104 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11105 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
11107 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11109 skip("Failed to create a YV12 overlay, skipping test.\n");
11110 goto done;
11113 memset(&desc, 0, sizeof(desc));
11114 desc.dwSize = sizeof(desc);
11115 hr = IDirectDrawSurface_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11116 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
11118 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
11119 "Got unexpected flags %#lx.\n", desc.dwFlags);
11120 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
11121 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
11122 "Got unexpected caps %#lx.\n", desc.ddsCaps.dwCaps);
11123 ok(desc.dwWidth == 256, "Got unexpected width %lu.\n", desc.dwWidth);
11124 ok(desc.dwHeight == 256, "Got unexpected height %lu.\n", desc.dwHeight);
11125 /* The overlay pitch seems to have 256 byte alignment. */
11126 ok(!(desc.lPitch & 0xff), "Got unexpected pitch %lu.\n", desc.lPitch);
11128 /* Fill the surface with some data for the blit test. */
11129 base = desc.lpSurface;
11130 /* Luminance */
11131 for (y = 0; y < desc.dwHeight; ++y)
11133 memset(base + desc.lPitch * y, 0x10, desc.dwWidth);
11135 /* V */
11136 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
11138 memset(base + desc.lPitch * y, 0x20, desc.dwWidth);
11140 /* U */
11141 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
11143 memset(base + desc.lPitch * y, 0x30, desc.dwWidth);
11146 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
11147 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
11149 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
11150 * other block-based formats like DXT the entire Y channel is stored in
11151 * one big chunk of memory, followed by the chroma channels. So partial
11152 * locks do not really make sense. Show that they are allowed nevertheless
11153 * and the offset points into the luminance data. */
11154 hr = IDirectDrawSurface_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
11155 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
11156 offset = ((const unsigned char *)desc.lpSurface - base);
11157 ok(offset == rect.top * desc.lPitch + rect.left, "Got unexpected offset %u, expected %lu.\n",
11158 offset, rect.top * desc.lPitch + rect.left);
11159 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
11160 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
11162 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11164 /* Windows XP with a Radeon X1600 GPU refuses to create a second
11165 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
11166 skip("Failed to create a second YV12 surface, skipping blit test.\n");
11167 IDirectDrawSurface_Release(src_surface);
11168 goto done;
11171 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
11172 /* VMware rejects YV12 blits. This behavior has not been seen on real
11173 * hardware yet, so mark it broken. */
11174 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#lx.\n", hr);
11176 if (SUCCEEDED(hr))
11178 memset(&desc, 0, sizeof(desc));
11179 desc.dwSize = sizeof(desc);
11180 hr = IDirectDrawSurface_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11181 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
11183 base = desc.lpSurface;
11184 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
11185 base += desc.dwHeight * desc.lPitch;
11186 ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
11187 base += desc.dwHeight / 4 * desc.lPitch;
11188 ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
11190 hr = IDirectDrawSurface_Unlock(dst_surface, NULL);
11191 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
11194 IDirectDrawSurface_Release(dst_surface);
11195 IDirectDrawSurface_Release(src_surface);
11196 done:
11197 IDirectDraw2_Release(ddraw);
11198 DestroyWindow(window);
11201 static BOOL dwm_enabled(void)
11203 BOOL ret = FALSE;
11205 if (!strcmp(winetest_platform, "wine"))
11206 return FALSE;
11207 if (!pDwmIsCompositionEnabled)
11208 return FALSE;
11209 if (FAILED(pDwmIsCompositionEnabled(&ret)))
11210 return FALSE;
11211 return ret;
11214 static void test_offscreen_overlay(void)
11216 IDirectDrawSurface *overlay, *offscreen, *primary;
11217 DDSURFACEDESC surface_desc;
11218 IDirectDraw2 *ddraw;
11219 HWND window;
11220 HRESULT hr;
11221 HDC dc;
11223 window = create_window();
11224 ddraw = create_ddraw();
11225 ok(!!ddraw, "Failed to create a ddraw object.\n");
11226 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11227 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
11229 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
11231 skip("Failed to create a UYVY overlay, skipping test.\n");
11232 goto done;
11235 memset(&surface_desc, 0, sizeof(surface_desc));
11236 surface_desc.dwSize = sizeof(surface_desc);
11237 surface_desc.dwFlags = DDSD_CAPS;
11238 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
11239 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
11240 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
11242 /* On Windows 7, and probably Vista, UpdateOverlay() will return
11243 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
11244 * surface prevents this by disabling the dwm. */
11245 hr = IDirectDrawSurface_GetDC(primary, &dc);
11246 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
11247 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
11248 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
11250 /* Try to overlay a NULL surface. */
11251 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
11252 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11253 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
11254 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11256 /* Try to overlay an offscreen surface. */
11257 memset(&surface_desc, 0, sizeof(surface_desc));
11258 surface_desc.dwSize = sizeof(surface_desc);
11259 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
11260 surface_desc.dwWidth = 64;
11261 surface_desc.dwHeight = 64;
11262 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11263 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
11264 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
11265 surface_desc.ddpfPixelFormat.dwFourCC = 0;
11266 surface_desc.ddpfPixelFormat.dwRGBBitCount = 16;
11267 surface_desc.ddpfPixelFormat.dwRBitMask = 0xf800;
11268 surface_desc.ddpfPixelFormat.dwGBitMask = 0x07e0;
11269 surface_desc.ddpfPixelFormat.dwBBitMask = 0x001f;
11270 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
11271 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
11273 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
11274 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled())
11275 || broken(hr == E_NOTIMPL && ddraw_is_vmware(ddraw)),
11276 "Failed to update overlay, hr %#lx.\n", hr);
11278 /* Try to overlay the primary with a non-overlay surface. */
11279 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
11280 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#lx.\n", hr);
11281 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
11282 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#lx.\n", hr);
11284 IDirectDrawSurface_Release(offscreen);
11285 IDirectDrawSurface_Release(primary);
11286 IDirectDrawSurface_Release(overlay);
11287 done:
11288 IDirectDraw2_Release(ddraw);
11289 DestroyWindow(window);
11292 static void test_overlay_rect(void)
11294 IDirectDrawSurface *overlay, *primary = NULL;
11295 DDSURFACEDESC surface_desc;
11296 RECT rect = {0, 0, 64, 64};
11297 IDirectDraw2 *ddraw;
11298 LONG pos_x, pos_y;
11299 HRESULT hr, hr2;
11300 HWND window;
11301 HDC dc;
11303 window = create_window();
11304 ddraw = create_ddraw();
11305 ok(!!ddraw, "Failed to create a ddraw object.\n");
11306 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11307 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
11309 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
11311 skip("Failed to create a UYVY overlay, skipping test.\n");
11312 goto done;
11315 memset(&surface_desc, 0, sizeof(surface_desc));
11316 surface_desc.dwSize = sizeof(surface_desc);
11317 surface_desc.dwFlags = DDSD_CAPS;
11318 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
11319 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
11320 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
11322 /* On Windows 7, and probably Vista, UpdateOverlay() will return
11323 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
11324 * surface prevents this by disabling the dwm. */
11325 hr = IDirectDrawSurface_GetDC(primary, &dc);
11326 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
11327 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
11328 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
11330 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
11331 if (dwm_enabled())
11333 win_skip("Cannot disable DWM, skipping overlay test.\n");
11334 goto done;
11337 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
11338 * used. This is not true in Windows Vista and earlier, but changed in
11339 * Windows 7. */
11340 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
11341 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#lx.\n", hr);
11342 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
11343 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#lx.\n", hr);
11344 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
11345 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11347 /* Show that the overlay position is the (top, left) coordinate of the
11348 * destination rectangle. */
11349 OffsetRect(&rect, 32, 16);
11350 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
11351 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#lx.\n", hr);
11352 pos_x = -1; pos_y = -1;
11353 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
11354 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#lx.\n", hr);
11355 ok(pos_x == rect.left, "Got unexpected pos_x %ld, expected %ld.\n", pos_x, rect.left);
11356 ok(pos_y == rect.top, "Got unexpected pos_y %ld, expected %ld.\n", pos_y, rect.top);
11358 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
11359 * seen that the overlay overlays the whole primary(==screen). */
11360 hr2 = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
11361 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#lx.\n", hr2);
11362 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
11363 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#lx.\n", hr);
11364 if (SUCCEEDED(hr2))
11366 ok(!pos_x, "Got unexpected pos_x %ld.\n", pos_x);
11367 ok(!pos_y, "Got unexpected pos_y %ld.\n", pos_y);
11369 else
11371 ok(pos_x == 32, "Got unexpected pos_x %ld.\n", pos_x);
11372 ok(pos_y == 16, "Got unexpected pos_y %ld.\n", pos_y);
11375 /* The position cannot be retrieved when the overlay is not shown. */
11376 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
11377 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#lx.\n", hr);
11378 pos_x = -1; pos_y = -1;
11379 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
11380 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#lx.\n", hr);
11381 ok(!pos_x, "Got unexpected pos_x %ld.\n", pos_x);
11382 ok(!pos_y, "Got unexpected pos_y %ld.\n", pos_y);
11384 done:
11385 if (primary)
11386 IDirectDrawSurface_Release(primary);
11387 if (overlay)
11388 IDirectDrawSurface_Release(overlay);
11389 IDirectDraw2_Release(ddraw);
11390 DestroyWindow(window);
11393 static void test_blt(void)
11395 IDirectDrawSurface *surface, *rt;
11396 DDSURFACEDESC surface_desc;
11397 IDirect3DDevice2 *device;
11398 IDirectDraw2 *ddraw;
11399 unsigned int i;
11400 ULONG refcount;
11401 HWND window;
11402 HRESULT hr;
11404 static struct
11406 RECT src_rect;
11407 RECT dst_rect;
11408 HRESULT hr;
11410 test_data[] =
11412 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
11413 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
11414 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
11415 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
11416 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
11417 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
11418 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
11419 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
11420 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
11421 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
11424 window = create_window();
11425 ddraw = create_ddraw();
11426 ok(!!ddraw, "Failed to create a ddraw object.\n");
11427 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
11429 skip("Failed to create a 3D device, skipping test.\n");
11430 IDirectDraw2_Release(ddraw);
11431 DestroyWindow(window);
11432 return;
11435 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
11436 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
11438 memset(&surface_desc, 0, sizeof(surface_desc));
11439 surface_desc.dwSize = sizeof(surface_desc);
11440 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
11441 surface_desc.dwWidth = 640;
11442 surface_desc.dwHeight = 480;
11443 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11444 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11445 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
11447 hr = IDirectDrawSurface_Blt(surface, NULL, surface, NULL, 0, NULL);
11448 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
11450 hr = IDirectDrawSurface_Blt(surface, NULL, rt, NULL, 0, NULL);
11451 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
11453 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
11455 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
11456 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11457 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n", i, hr, test_data[i].hr);
11459 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
11460 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11461 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n", i, hr, test_data[i].hr);
11463 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
11464 NULL, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11465 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#lx.\n", i, hr);
11467 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect, NULL, NULL, DDBLT_WAIT, NULL);
11468 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#lx.\n", i, hr);
11471 IDirectDrawSurface_Release(surface);
11472 IDirectDrawSurface_Release(rt);
11473 refcount = IDirect3DDevice2_Release(device);
11474 ok(!refcount, "Device has %lu references left.\n", refcount);
11475 IDirectDraw2_Release(ddraw);
11476 DestroyWindow(window);
11479 static void test_blt_z_alpha(void)
11481 DWORD blt_flags[] =
11483 /* 0 */
11484 DDBLT_ALPHADEST,
11485 DDBLT_ALPHADESTCONSTOVERRIDE,
11486 DDBLT_ALPHADESTNEG,
11487 DDBLT_ALPHADESTSURFACEOVERRIDE,
11488 DDBLT_ALPHAEDGEBLEND,
11489 /* 5 */
11490 DDBLT_ALPHASRC,
11491 DDBLT_ALPHASRCCONSTOVERRIDE,
11492 DDBLT_ALPHASRCNEG,
11493 DDBLT_ALPHASRCSURFACEOVERRIDE,
11494 DDBLT_ZBUFFER,
11495 /* 10 */
11496 DDBLT_ZBUFFERDESTCONSTOVERRIDE,
11497 DDBLT_ZBUFFERDESTOVERRIDE,
11498 DDBLT_ZBUFFERSRCCONSTOVERRIDE,
11499 DDBLT_ZBUFFERSRCOVERRIDE,
11501 IDirectDrawSurface *src_surface, *dst_surface;
11502 DDSURFACEDESC surface_desc;
11503 unsigned int color, i;
11504 IDirectDraw2 *ddraw;
11505 DDPIXELFORMAT pf;
11506 ULONG refcount;
11507 HWND window;
11508 HRESULT hr;
11509 DDBLTFX fx;
11511 window = create_window();
11512 ddraw = create_ddraw();
11513 ok(!!ddraw, "Failed to create a ddraw object.\n");
11514 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11515 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
11517 memset(&pf, 0, sizeof(pf));
11518 pf.dwSize = sizeof(pf);
11519 pf.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
11520 pf.dwRGBBitCount = 32;
11521 pf.dwRBitMask = 0x00ff0000;
11522 pf.dwGBitMask = 0x0000ff00;
11523 pf.dwBBitMask = 0x000000ff;
11524 pf.dwRGBAlphaBitMask = 0xff000000;
11526 memset(&surface_desc, 0, sizeof(surface_desc));
11527 surface_desc.dwSize = sizeof(surface_desc);
11528 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
11529 surface_desc.dwWidth = 64;
11530 surface_desc.dwHeight = 64;
11531 surface_desc.ddpfPixelFormat = pf;
11532 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11534 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
11535 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#lx.\n", hr);
11536 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
11537 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#lx.\n", hr);
11539 memset(&fx, 0, sizeof(fx));
11540 fx.dwSize = sizeof(fx);
11541 fx.dwZBufferOpCode = D3DCMP_NEVER;
11542 fx.dwZDestConstBitDepth = 32;
11543 fx.dwZDestConst = 0x11111111;
11544 fx.dwZSrcConstBitDepth = 32;
11545 fx.dwZSrcConst = 0xeeeeeeee;
11546 fx.dwAlphaEdgeBlendBitDepth = 8;
11547 fx.dwAlphaEdgeBlend = 0x7f;
11548 fx.dwAlphaDestConstBitDepth = 8;
11549 fx.dwAlphaDestConst = 0xdd;
11550 fx.dwAlphaSrcConstBitDepth = 8;
11551 fx.dwAlphaSrcConst = 0x22;
11553 for (i = 0; i < ARRAY_SIZE(blt_flags); ++i)
11555 fx.dwFillColor = 0x3300ff00;
11556 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11557 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#lx.\n", i, hr);
11559 fx.dwFillColor = 0xccff0000;
11560 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11561 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#lx.\n", i, hr);
11563 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, NULL, blt_flags[i] | DDBLT_WAIT, &fx);
11564 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#lx.\n", i, hr);
11566 color = get_surface_color(dst_surface, 32, 32);
11567 ok(compare_color(color, 0x0000ff00, 0), "Test %u: Got unexpected color 0x%08x.\n", i, color);
11570 IDirectDrawSurface_Release(dst_surface);
11571 IDirectDrawSurface_Release(src_surface);
11572 refcount = IDirectDraw2_Release(ddraw);
11573 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
11574 DestroyWindow(window);
11577 static void test_cross_device_blt(void)
11579 IDirectDrawSurface *surface, *surface2, *sysmem_surface;
11580 IDirect3DDevice2 *device, *device2;
11581 IDirectDraw2 *ddraw, *ddraw2;
11582 DDSURFACEDESC surface_desc;
11583 HWND window, window2;
11584 unsigned int color;
11585 ULONG refcount;
11586 DDBLTFX fx;
11587 HRESULT hr;
11589 window = create_window();
11590 ddraw = create_ddraw();
11591 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
11593 skip("Failed to create a 3D device.\n");
11594 IDirectDraw2_Release(ddraw);
11595 DestroyWindow(window);
11596 return;
11599 window2 = create_window();
11600 ddraw2 = create_ddraw();
11601 if (!(device2 = create_device(ddraw2, window2, DDSCL_NORMAL)))
11603 skip("Failed to create a 3D device.\n");
11604 IDirectDraw2_Release(ddraw2);
11605 IDirect3DDevice2_Release(device);
11606 IDirectDraw2_Release(ddraw);
11607 DestroyWindow(window);
11608 DestroyWindow(window2);
11609 return;
11612 memset(&surface_desc, 0, sizeof(surface_desc));
11613 surface_desc.dwSize = sizeof(surface_desc);
11614 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
11615 surface_desc.dwWidth = 640;
11616 surface_desc.dwHeight = 480;
11617 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
11618 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
11619 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
11621 memset(&surface_desc, 0, sizeof(surface_desc));
11622 surface_desc.dwSize = sizeof(surface_desc);
11623 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
11624 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
11625 surface_desc.dwBackBufferCount = 2;
11626 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11627 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
11629 memset(&surface_desc, 0, sizeof(surface_desc));
11630 surface_desc.dwSize = sizeof(surface_desc);
11631 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
11632 surface_desc.dwWidth = 640;
11633 surface_desc.dwHeight = 480;
11634 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
11635 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
11636 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
11637 surface_desc.ddpfPixelFormat.dwRGBBitCount = 16;
11638 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00007c00;
11639 surface_desc.ddpfPixelFormat.dwGBitMask = 0x000003e0;
11640 surface_desc.ddpfPixelFormat.dwBBitMask = 0x0000001f;
11641 hr = IDirectDraw2_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
11642 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
11644 memset(&fx, 0, sizeof(fx));
11645 fx.dwSize = sizeof(fx);
11646 fx.dwFillColor = 0xff0000ff;
11647 hr = IDirectDrawSurface_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11648 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#lx.\n", hr);
11650 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
11651 ok(hr == E_NOTIMPL, "Got unexpected hr %#lx.\n", hr);
11652 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
11653 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
11654 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
11655 ok(hr == E_NOTIMPL, "Got unexpected hr %#lx.\n", hr);
11656 color = get_surface_color(surface, 320, 240);
11657 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
11659 hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
11660 ok(hr == E_NOTIMPL, "Got unexpected hr %#lx.\n", hr);
11661 color = get_surface_color(sysmem_surface, 320, 240);
11662 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
11664 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11665 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
11666 hr = IDirectDrawSurface_IsLost(sysmem_surface);
11667 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11669 hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
11670 ok(hr == E_NOTIMPL, "Got unexpected hr %#lx.\n", hr);
11671 color = get_surface_color(sysmem_surface, 320, 240);
11672 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
11674 IDirectDrawSurface_Release(surface2);
11675 memset(&surface_desc, 0, sizeof(surface_desc));
11676 surface_desc.dwSize = sizeof(surface_desc);
11677 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
11678 surface_desc.dwWidth = 640;
11679 surface_desc.dwHeight = 480;
11680 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
11681 hr = IDirectDraw2_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
11682 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
11683 hr = IDirectDrawSurface_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11684 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#lx.\n", hr);
11686 hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
11687 todo_wine ok(hr == D3D_OK, "Failed to blit, hr %#lx.\n", hr);
11688 color = get_surface_color(sysmem_surface, 320, 240);
11689 todo_wine ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
11691 IDirectDrawSurface_Release(surface);
11692 IDirectDrawSurface_Release(surface2);
11693 IDirectDrawSurface_Release(sysmem_surface);
11694 refcount = IDirect3DDevice2_Release(device);
11695 ok(!refcount, "Device has %lu references left.\n", refcount);
11696 refcount = IDirect3DDevice2_Release(device2);
11697 ok(!refcount, "Device has %lu references left.\n", refcount);
11698 IDirectDraw2_Release(ddraw);
11699 IDirectDraw2_Release(ddraw2);
11700 DestroyWindow(window);
11701 DestroyWindow(window2);
11704 static void test_getdc(void)
11706 IDirectDrawSurface *surface, *surface2, *tmp;
11707 DDSURFACEDESC surface_desc, map_desc;
11708 DDSCAPS caps = {DDSCAPS_COMPLEX};
11709 IDirectDraw2 *ddraw;
11710 unsigned int i, screen_bpp;
11711 HWND window;
11712 HDC dc, dc2;
11713 HRESULT hr;
11715 static const struct
11717 const char *name;
11718 DDPIXELFORMAT format;
11719 BOOL getdc_supported;
11720 HRESULT alt_result;
11722 test_data[] =
11724 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11725 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
11726 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
11727 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
11728 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11729 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
11730 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11731 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
11732 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
11733 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
11734 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
11735 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11736 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11737 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11738 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11739 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
11740 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11741 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11742 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
11743 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11744 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
11745 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
11746 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
11747 * This is not implemented in wine yet, so disable the test for now.
11748 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
11749 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
11750 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11752 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
11753 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11754 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
11755 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
11756 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
11757 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11758 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
11759 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11760 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
11761 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11762 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
11763 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11764 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
11765 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11768 window = create_window();
11769 ddraw = create_ddraw();
11770 ok(!!ddraw, "Failed to create a ddraw object.\n");
11771 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11772 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
11774 surface_desc.dwSize = sizeof(surface_desc);
11775 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
11776 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#lx.\n", hr);
11777 screen_bpp = surface_desc.ddpfPixelFormat.dwRGBBitCount;
11779 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
11781 memset(&surface_desc, 0, sizeof(surface_desc));
11782 surface_desc.dwSize = sizeof(surface_desc);
11783 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11784 surface_desc.dwWidth = 64;
11785 surface_desc.dwHeight = 64;
11786 surface_desc.ddpfPixelFormat = test_data[i].format;
11787 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11789 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11791 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11792 if (FAILED(hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11794 skip("Failed to create surface for format %s (hr %#lx), skipping tests.\n", test_data[i].name, hr);
11795 continue;
11799 dc = (void *)0x1234;
11800 hr = IDirectDrawSurface_GetDC(surface, &dc);
11801 if (test_data[i].getdc_supported)
11802 ok(SUCCEEDED(hr) || broken(hr == test_data[i].alt_result || ddraw_is_vmware(ddraw)),
11803 "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11804 else
11805 ok(FAILED(hr), "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11807 if (SUCCEEDED(hr))
11809 unsigned int width_bytes;
11810 DIBSECTION dib;
11811 HBITMAP bitmap;
11812 DWORD type;
11813 int size;
11815 type = GetObjectType(dc);
11816 ok(type == OBJ_MEMDC, "Got unexpected object type %#lx for format %s.\n", type, test_data[i].name);
11817 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
11818 type = GetObjectType(bitmap);
11819 ok(type == OBJ_BITMAP, "Got unexpected object type %#lx for format %s.\n", type, test_data[i].name);
11821 size = GetObjectA(bitmap, sizeof(dib), &dib);
11822 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
11823 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
11824 dib.dsBm.bmType, test_data[i].name);
11825 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
11826 dib.dsBm.bmWidth, test_data[i].name);
11827 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
11828 dib.dsBm.bmHeight, test_data[i].name);
11829 width_bytes = ((dib.dsBm.bmWidth * test_data[i].format.dwRGBBitCount + 31) >> 3) & ~3;
11830 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
11831 dib.dsBm.bmWidthBytes, test_data[i].name);
11832 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
11833 dib.dsBm.bmPlanes, test_data[i].name);
11834 ok(dib.dsBm.bmBitsPixel == test_data[i].format.dwRGBBitCount,
11835 "Got unexpected bit count %d for format %s.\n",
11836 dib.dsBm.bmBitsPixel, test_data[i].name);
11837 /* Windows XP sets bmBits == NULL for formats that match the screen at least on my r200 GPU. I
11838 * suspect this applies to all HW accelerated pre-WDDM drivers because they can handle gdi access
11839 * to ddraw surfaces themselves instead of going through a sysmem DIB section. */
11840 ok(!!dib.dsBm.bmBits || broken(!pDwmIsCompositionEnabled && dib.dsBm.bmBitsPixel == screen_bpp),
11841 "Got unexpected bits %p for format %s.\n", dib.dsBm.bmBits, test_data[i].name);
11843 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %lu for format %s.\n",
11844 dib.dsBmih.biSize, test_data[i].name);
11845 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %ld for format %s.\n",
11846 dib.dsBmih.biHeight, test_data[i].name);
11847 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %ld for format %s.\n",
11848 dib.dsBmih.biHeight, test_data[i].name);
11849 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
11850 dib.dsBmih.biPlanes, test_data[i].name);
11851 ok(dib.dsBmih.biBitCount == test_data[i].format.dwRGBBitCount,
11852 "Got unexpected bit count %u for format %s.\n",
11853 dib.dsBmih.biBitCount, test_data[i].name);
11854 ok(dib.dsBmih.biCompression == (test_data[i].format.dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
11855 || broken(test_data[i].format.dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
11856 "Got unexpected compression %#lx for format %s.\n",
11857 dib.dsBmih.biCompression, test_data[i].name);
11858 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %lu for format %s.\n",
11859 dib.dsBmih.biSizeImage, test_data[i].name);
11860 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %ld for format %s.\n",
11861 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
11862 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %ld for format %s.\n",
11863 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
11864 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %lu for format %s.\n",
11865 dib.dsBmih.biClrUsed, test_data[i].name);
11866 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %lu for format %s.\n",
11867 dib.dsBmih.biClrImportant, test_data[i].name);
11869 if (dib.dsBmih.biCompression == BI_BITFIELDS)
11871 ok((dib.dsBitfields[0] == test_data[i].format.dwRBitMask
11872 && dib.dsBitfields[1] == test_data[i].format.dwGBitMask
11873 && dib.dsBitfields[2] == test_data[i].format.dwBBitMask)
11874 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
11875 "Got unexpected colour masks 0x%08lx 0x%08lx 0x%08lx for format %s.\n",
11876 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11878 else
11880 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
11881 "Got unexpected colour masks 0x%08lx 0x%08lx 0x%08lx for format %s.\n",
11882 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11884 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
11885 ok(!dib.dsOffset, "Got unexpected offset %lu for format %s.\n", dib.dsOffset, test_data[i].name);
11887 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11888 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11890 else
11892 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
11895 IDirectDrawSurface_Release(surface);
11897 if (FAILED(hr))
11898 continue;
11900 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
11901 if (FAILED(hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11903 skip("Failed to create mip-mapped texture for format %s (hr %#lx), skipping tests.\n",
11904 test_data[i].name, hr);
11905 continue;
11908 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
11909 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11910 hr = IDirectDrawSurface_GetAttachedSurface(tmp, &caps, &surface2);
11911 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11912 IDirectDrawSurface_Release(tmp);
11914 hr = IDirectDrawSurface_GetDC(surface, &dc);
11915 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11916 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11917 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11918 hr = IDirectDrawSurface_GetDC(surface2, &dc);
11919 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11920 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
11921 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11923 hr = IDirectDrawSurface_GetDC(surface, &dc);
11924 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11925 dc2 = (void *)0x1234;
11926 hr = IDirectDrawSurface_GetDC(surface, &dc2);
11927 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11928 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
11929 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11930 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11931 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11932 ok(hr == DDERR_NODC, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11934 map_desc.dwSize = sizeof(map_desc);
11935 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11936 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11937 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11938 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11939 hr = IDirectDrawSurface_Unlock(surface, NULL);
11940 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11941 hr = IDirectDrawSurface_Unlock(surface, NULL);
11942 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11944 hr = IDirectDrawSurface_GetDC(surface, &dc);
11945 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11946 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11947 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
11948 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11949 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11951 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11952 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11953 hr = IDirectDrawSurface_GetDC(surface, &dc);
11954 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11955 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11956 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11957 /* Geforce 9600, Windows 7 returns E_FAIL. The unlock still seems to work as intended, after-
11958 * wards the surface can be locked again. ReleaseDC() does not unlock the surface, trying to
11959 * Lock it after ReleaseDC returns DDERR_SURFACEBUSY. ddraw4 and 7 are unaffected. */
11960 hr = IDirectDrawSurface_Unlock(surface, NULL);
11961 ok(SUCCEEDED(hr) || broken(ddraw_is_nvidia(ddraw) && hr == E_FAIL),
11962 "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11964 hr = IDirectDrawSurface_GetDC(surface, &dc);
11965 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11966 hr = IDirectDrawSurface_GetDC(surface2, &dc2);
11967 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11968 hr = IDirectDrawSurface_ReleaseDC(surface2, dc2);
11969 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11970 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11971 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11973 hr = IDirectDrawSurface_GetDC(surface2, &dc);
11974 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11975 hr = IDirectDrawSurface_GetDC(surface, &dc2);
11976 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11977 hr = IDirectDrawSurface_ReleaseDC(surface, dc2);
11978 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11979 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
11980 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11982 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11983 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11984 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11985 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11986 hr = IDirectDrawSurface_Unlock(surface2, NULL);
11987 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11988 hr = IDirectDrawSurface_Unlock(surface, NULL);
11989 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11991 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11992 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
11993 hr = IDirectDrawSurface_GetDC(surface, &dc);
11994 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11995 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11996 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
11997 hr = IDirectDrawSurface_Unlock(surface, NULL);
11998 ok(SUCCEEDED(hr) || broken(ddraw_is_nvidia(ddraw) && hr == E_FAIL),
11999 "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
12001 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12002 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
12003 hr = IDirectDrawSurface_GetDC(surface, &dc);
12004 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
12005 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
12006 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
12007 hr = IDirectDrawSurface_Unlock(surface2, NULL);
12008 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
12010 hr = IDirectDrawSurface_GetDC(surface, &dc);
12011 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
12012 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12013 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
12014 hr = IDirectDrawSurface_Unlock(surface2, NULL);
12015 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
12016 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
12017 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
12019 hr = IDirectDrawSurface_GetDC(surface2, &dc);
12020 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
12021 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12022 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
12023 hr = IDirectDrawSurface_Unlock(surface, NULL);
12024 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
12025 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
12026 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
12028 hr = IDirectDrawSurface_Unlock(surface, NULL);
12029 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
12030 hr = IDirectDrawSurface_GetDC(surface2, &dc);
12031 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
12032 hr = IDirectDrawSurface_Unlock(surface, NULL);
12033 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
12034 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
12035 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
12036 hr = IDirectDrawSurface_Unlock(surface, NULL);
12037 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
12039 hr = IDirectDrawSurface_Unlock(surface2, NULL);
12040 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
12041 hr = IDirectDrawSurface_GetDC(surface, &dc);
12042 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
12043 hr = IDirectDrawSurface_Unlock(surface2, NULL);
12044 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
12045 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
12046 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
12047 hr = IDirectDrawSurface_Unlock(surface2, NULL);
12048 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
12050 IDirectDrawSurface_Release(surface2);
12051 IDirectDrawSurface_Release(surface);
12054 IDirectDraw2_Release(ddraw);
12055 DestroyWindow(window);
12058 static void test_draw_primitive(void)
12060 static WORD indices[] = {0, 1, 2, 3};
12061 static D3DVERTEX quad[] =
12063 {{-1.0f}, {-1.0f}, {0.0f}},
12064 {{-1.0f}, { 1.0f}, {0.0f}},
12065 {{ 1.0f}, {-1.0f}, {0.0f}},
12066 {{ 1.0f}, { 1.0f}, {0.0f}},
12068 IDirect3DViewport2 *viewport;
12069 IDirect3DDevice2 *device;
12070 IDirectDraw2 *ddraw;
12071 IDirect3D2 *d3d;
12072 ULONG refcount;
12073 HWND window;
12074 HRESULT hr;
12076 window = create_window();
12077 ddraw = create_ddraw();
12078 ok(!!ddraw, "Failed to create a ddraw object.\n");
12079 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
12081 skip("Failed to create a 3D device, skipping test.\n");
12082 IDirectDraw2_Release(ddraw);
12083 DestroyWindow(window);
12084 return;
12087 viewport = create_viewport(device, 0, 0, 640, 480);
12088 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
12089 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#lx.\n", hr);
12091 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
12092 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#lx.\n", hr);
12094 IDirect3D2_Release(d3d);
12096 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
12097 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12098 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
12099 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12101 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
12102 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12104 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
12105 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12106 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
12107 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12108 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
12109 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12111 destroy_viewport(device, viewport);
12112 refcount = IDirect3DDevice2_Release(device);
12113 ok(!refcount, "Device has %lu references left.\n", refcount);
12114 IDirectDraw2_Release(ddraw);
12115 DestroyWindow(window);
12118 static void test_edge_antialiasing_blending(void)
12120 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
12121 IDirect3DMaterial2 *green_background;
12122 IDirect3DMaterial2 *red_background;
12123 IDirectDrawSurface *offscreen, *ds;
12124 D3DDEVICEDESC hal_desc, hel_desc;
12125 IDirect3DViewport2 *viewport;
12126 DDSURFACEDESC surface_desc;
12127 IDirect3DDevice2 *device;
12128 IDirectDraw2 *ddraw;
12129 unsigned int color;
12130 ULONG refcount;
12131 HWND window;
12132 HRESULT hr;
12134 static D3DMATRIX mat =
12136 1.0f, 0.0f, 0.0f, 0.0f,
12137 0.0f, 1.0f, 0.0f, 0.0f,
12138 0.0f, 0.0f, 1.0f, 0.0f,
12139 0.0f, 0.0f, 0.0f, 1.0f,
12141 static D3DLVERTEX green_quad[] =
12143 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0x7f00ff00}},
12144 {{-1.0f}, { 1.0f}, {0.1f}, 0, {0x7f00ff00}},
12145 {{ 1.0f}, {-1.0f}, {0.1f}, 0, {0x7f00ff00}},
12146 {{ 1.0f}, { 1.0f}, {0.1f}, 0, {0x7f00ff00}},
12148 static D3DLVERTEX red_quad[] =
12150 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0xccff0000}},
12151 {{-1.0f}, { 1.0f}, {0.1f}, 0, {0xccff0000}},
12152 {{ 1.0f}, {-1.0f}, {0.1f}, 0, {0xccff0000}},
12153 {{ 1.0f}, { 1.0f}, {0.1f}, 0, {0xccff0000}},
12156 window = create_window();
12157 ddraw = create_ddraw();
12158 ok(!!ddraw, "Failed to create a ddraw object.\n");
12159 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
12161 skip("Failed to create a 3D device.\n");
12162 DestroyWindow(window);
12163 return;
12166 memset(&hal_desc, 0, sizeof(hal_desc));
12167 hal_desc.dwSize = sizeof(hal_desc);
12168 memset(&hel_desc, 0, sizeof(hel_desc));
12169 hel_desc.dwSize = sizeof(hel_desc);
12170 hr = IDirect3DDevice2_GetCaps(device, &hal_desc, &hel_desc);
12171 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#lx.\n", hr);
12172 trace("HAL line edge antialiasing support: %#lx.\n",
12173 hal_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12174 trace("HAL triangle edge antialiasing support: %#lx.\n",
12175 hal_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12176 trace("HEL line edge antialiasing support: %#lx.\n",
12177 hel_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12178 trace("HEL triangle edge antialiasing support: %#lx.\n",
12179 hel_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12181 memset(&surface_desc, 0, sizeof(surface_desc));
12182 surface_desc.dwSize = sizeof(surface_desc);
12183 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
12184 surface_desc.dwWidth = 640;
12185 surface_desc.dwHeight = 480;
12186 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
12187 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
12188 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12189 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
12190 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
12191 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
12192 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
12193 surface_desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
12194 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
12195 ok(hr == D3D_OK, "Creating the offscreen render target failed, hr %#lx.\n", hr);
12197 ds = get_depth_stencil(device);
12198 hr = IDirectDrawSurface_AddAttachedSurface(offscreen, ds);
12199 todo_wine ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#lx.\n", hr);
12200 IDirectDrawSurface_Release(ds);
12202 hr = IDirect3DDevice2_SetRenderTarget(device, offscreen, 0);
12203 ok(SUCCEEDED(hr), "Failed to set render target, hr %#lx.\n", hr);
12205 red_background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 0.8f);
12206 green_background = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.5f);
12208 viewport = create_viewport(device, 0, 0, 640, 480);
12209 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
12210 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#lx.\n", hr);
12212 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
12213 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
12214 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
12215 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#lx.\n", hr);
12216 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
12217 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#lx.\n", hr);
12218 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
12219 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#lx.\n", hr);
12220 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
12221 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#lx.\n", hr);
12222 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
12223 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#lx.\n", hr);
12225 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
12226 ok(SUCCEEDED(hr), "Failed to enable blending, hr %#lx.\n", hr);
12227 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
12228 ok(SUCCEEDED(hr), "Failed to set src blend, hr %#lx.\n", hr);
12229 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
12230 ok(SUCCEEDED(hr), "Failed to set dest blend, hr %#lx.\n", hr);
12232 viewport_set_background(device, viewport, red_background);
12233 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
12234 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
12235 hr = IDirect3DDevice2_BeginScene(device);
12236 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
12237 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, green_quad, 4, 0);
12238 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12239 hr = IDirect3DDevice2_EndScene(device);
12240 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
12241 color = get_surface_color(offscreen, 320, 240);
12242 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
12244 viewport_set_background(device, viewport, green_background);
12245 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
12246 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
12247 hr = IDirect3DDevice2_BeginScene(device);
12248 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
12249 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, red_quad, 4, 0);
12250 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12251 hr = IDirect3DDevice2_EndScene(device);
12252 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
12253 color = get_surface_color(offscreen, 320, 240);
12254 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
12256 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
12257 ok(SUCCEEDED(hr), "Failed to disable blending, hr %#lx.\n", hr);
12259 viewport_set_background(device, viewport, red_background);
12260 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
12261 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
12262 hr = IDirect3DDevice2_BeginScene(device);
12263 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
12264 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, green_quad, 4, 0);
12265 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12266 hr = IDirect3DDevice2_EndScene(device);
12267 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
12268 color = get_surface_color(offscreen, 320, 240);
12269 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12271 viewport_set_background(device, viewport, green_background);
12272 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
12273 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
12274 hr = IDirect3DDevice2_BeginScene(device);
12275 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
12276 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, red_quad, 4, 0);
12277 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12278 hr = IDirect3DDevice2_EndScene(device);
12279 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
12280 color = get_surface_color(offscreen, 320, 240);
12281 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12283 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_EDGEANTIALIAS, TRUE);
12284 ok(SUCCEEDED(hr), "Failed to enable edge antialiasing, hr %#lx.\n", hr);
12286 viewport_set_background(device, viewport, red_background);
12287 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
12288 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
12289 hr = IDirect3DDevice2_BeginScene(device);
12290 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
12291 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, green_quad, 4, 0);
12292 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12293 hr = IDirect3DDevice2_EndScene(device);
12294 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
12295 color = get_surface_color(offscreen, 320, 240);
12296 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12298 viewport_set_background(device, viewport, green_background);
12299 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
12300 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
12301 hr = IDirect3DDevice2_BeginScene(device);
12302 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
12303 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, red_quad, 4, 0);
12304 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12305 hr = IDirect3DDevice2_EndScene(device);
12306 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
12307 color = get_surface_color(offscreen, 320, 240);
12308 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12310 IDirectDrawSurface_Release(offscreen);
12311 destroy_viewport(device, viewport);
12312 destroy_material(red_background);
12313 destroy_material(green_background);
12314 refcount = IDirect3DDevice2_Release(device);
12315 ok(!refcount, "Device has %lu references left.\n", refcount);
12316 IDirectDraw2_Release(ddraw);
12317 DestroyWindow(window);
12320 /* TransformVertices always writes 32 bytes regardless of the input / output stride.
12321 * The stride is honored for navigating to the next vertex. 3 floats input position
12322 * are read, and 16 bytes extra vertex data are copied around. */
12323 struct transform_input
12325 float x, y, z, unused1; /* Position data, transformed. */
12326 DWORD v1, v2, v3, v4; /* Extra data, e.g. color and texture coords, copied. */
12327 DWORD unused2;
12330 struct transform_output
12332 float x, y, z, w;
12333 unsigned int v1, v2, v3, v4;
12334 unsigned int unused3, unused4;
12337 static void test_transform_vertices(void)
12339 IDirect3DDevice2 *device;
12340 IDirectDrawSurface *rt;
12341 unsigned int color, i;
12342 IDirectDraw2 *ddraw;
12343 ULONG refcount;
12344 HWND window;
12345 HRESULT hr;
12346 IDirect3DViewport2 *viewport;
12347 IDirect3DMaterial2 *background;
12348 D3DMATERIAL mat;
12349 static struct transform_input position_tests[] =
12351 { 0.0f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
12352 { 1.0f, 1.0f, 1.0f, 8.0f, 6, 7, 8, 9, 10},
12353 {-1.0f, -1.0f, -1.0f, 4.0f, 11, 12, 13, 14, 15},
12354 { 0.5f, 0.5f, 0.5f, 2.0f, 16, 17, 18, 19, 20},
12355 {-0.5f, -0.5f, -0.5f, 1.0f, ~1U, ~2U, ~3U, ~4U, ~5U},
12356 {-0.5f, -0.5f, 0.0f, 0.0f, ~6U, ~7U, ~8U, ~9U, ~0U},
12358 static struct transform_input cliptest[] =
12360 { 25.59f, 25.59f, 1.0f, 0.0f, 1, 2, 3, 4, 5},
12361 { 25.61f, 25.61f, 1.01f, 0.0f, 1, 2, 3, 4, 5},
12362 {-25.59f, -25.59f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
12363 {-25.61f, -25.61f, -0.01f, 0.0f, 1, 2, 3, 4, 5},
12365 static struct transform_input offscreentest[] =
12367 {128.1f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
12369 struct transform_output out[ARRAY_SIZE(position_tests)];
12370 D3DHVERTEX out_h[ARRAY_SIZE(position_tests)];
12371 D3DTRANSFORMDATA transformdata;
12372 static const D3DVIEWPORT vp_template =
12374 sizeof(vp_template), 0, 0, 256, 256, 5.0f, 5.0f, 256.0f, 256.0f, -25.0f, 60.0f
12376 D3DVIEWPORT vp_data =
12378 sizeof(vp_data), 0, 0, 256, 256, 1.0f, 1.0f, 256.0f, 256.0f, 0.0f, 1.0f
12380 D3DVIEWPORT2 vp2_data;
12381 DWORD offscreen;
12382 static D3DMATRIX mat_scale =
12384 2.0f, 0.0f, 0.0f, 0.0f,
12385 0.0f, 2.0f, 0.0f, 0.0f,
12386 0.0f, 0.0f, 2.0f, 0.0f,
12387 0.0f, 0.0f, 0.0f, 1.0f,
12389 mat_translate1 =
12391 1.0f, 0.0f, 0.0f, 0.0f,
12392 0.0f, 1.0f, 0.0f, 0.0f,
12393 0.0f, 0.0f, 1.0f, 0.0f,
12394 1.0f, 0.0f, 0.0f, 1.0f,
12396 mat_translate2 =
12398 1.0f, 0.0f, 0.0f, 0.0f,
12399 0.0f, 1.0f, 0.0f, 0.0f,
12400 0.0f, 0.0f, 1.0f, 0.0f,
12401 0.0f, 1.0f, 0.0f, 1.0f,
12403 mat_transform3 =
12405 1.0f, 0.0f, 0.0f, 0.0f,
12406 0.0f, 1.0f, 0.0f, 0.0f,
12407 0.0f, 0.0f, 1.0f, 0.0f,
12408 0.0f, 19.2f, 0.0f, 2.0f,
12410 mat_identity =
12412 1.0f, 0.0f, 0.0f, 0.0f,
12413 0.0f, 1.0f, 0.0f, 0.0f,
12414 0.0f, 0.0f, 1.0f, 0.0f,
12415 0.0f, 0.0f, 0.0f, 1.0f,
12417 static D3DLVERTEX quad[] =
12419 {{-0.75f},{-0.5f }, {0.0f}, 0, {0xffff0000}},
12420 {{-0.75f},{ 0.25f}, {0.0f}, 0, {0xffff0000}},
12421 {{ 0.5f}, {-0.5f }, {0.0f}, 0, {0xffff0000}},
12422 {{ 0.5f}, { 0.25f}, {0.0f}, 0, {0xffff0000}},
12424 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
12427 for (i = 0; i < ARRAY_SIZE(out); ++i)
12429 out[i].unused3 = 0xdeadbeef;
12430 out[i].unused4 = 0xcafecafe;
12433 window = create_window();
12434 ddraw = create_ddraw();
12435 ok(!!ddraw, "Failed to create a ddraw object.\n");
12436 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
12438 skip("Failed to create a 3D device, skipping test.\n");
12439 IDirectDraw2_Release(ddraw);
12440 DestroyWindow(window);
12441 return;
12443 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
12444 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
12446 viewport = create_viewport(device, 0, 0, 256, 256);
12447 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12448 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
12450 memset(&transformdata, 0, sizeof(transformdata));
12451 transformdata.dwSize = sizeof(transformdata);
12452 transformdata.lpIn = position_tests;
12453 transformdata.dwInSize = sizeof(position_tests[0]);
12454 transformdata.lpOut = out;
12455 transformdata.dwOutSize = sizeof(out[0]);
12456 transformdata.lpHOut = NULL;
12458 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12459 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12460 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12461 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
12463 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12465 static const struct vec4 cmp[] =
12467 {128.0f, 128.0f, 0.0f, 1.0f}, {129.0f, 127.0f, 1.0f, 1.0f}, {127.0f, 129.0f, -1.0f, 1.0f},
12468 {128.5f, 127.5f, 0.5f, 1.0f}, {127.5f, 128.5f, -0.5f, 1.0f}, {127.5f, 128.5f, 0.0f, 1.0f}
12471 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12472 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
12473 out[i].x, out[i].y, out[i].z, out[i].w);
12474 ok(out[i].v1 == position_tests[i].v1 && out[i].v2 == position_tests[i].v2
12475 && out[i].v3 == position_tests[i].v3 && out[i].v4 == position_tests[i].v4,
12476 "Vertex %u payload is %u %u %u %u.\n", i, out[i].v1, out[i].v2, out[i].v3, out[i].v4);
12477 ok(out[i].unused3 == 0xdeadbeef && out[i].unused4 == 0xcafecafe,
12478 "Vertex %u unused data is %#x, %#x.\n", i, out[i].unused3, out[i].unused4);
12481 vp_data = vp_template;
12482 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12483 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
12484 offscreen = 0xdeadbeef;
12485 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12486 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12487 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12488 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
12490 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12492 static const struct vec4 cmp[] =
12494 {128.0f, 128.0f, 0.0f, 1.0f}, {133.0f, 123.0f, 1.0f, 1.0f}, {123.0f, 133.0f, -1.0f, 1.0f},
12495 {130.5f, 125.5f, 0.5f, 1.0f}, {125.5f, 130.5f, -0.5f, 1.0f}, {125.5f, 130.5f, 0.0f, 1.0f}
12497 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12498 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
12499 out[i].x, out[i].y, out[i].z, out[i].w);
12502 vp_data.dwX = 10;
12503 vp_data.dwY = 20;
12504 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12505 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
12506 offscreen = 0xdeadbeef;
12507 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12508 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12509 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12510 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
12511 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12513 static const struct vec4 cmp[] =
12515 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, {133.0f, 153.0f, -1.0f, 1.0f},
12516 {140.5f, 145.5f, 0.5f, 1.0f}, {135.5f, 150.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
12518 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12519 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
12520 out[i].x, out[i].y, out[i].z, out[i].w);
12523 transformdata.lpHOut = out_h;
12524 offscreen = 0xdeadbeef;
12525 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12526 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12527 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12528 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
12529 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12531 static const D3DHVERTEX cmp_h[] =
12533 {0, { 0.0f}, { 0.0f}, { 0.0f}}, {0, { 1.0f}, { 1.0f}, {1.0f}},
12534 {D3DCLIP_FRONT, {-1.0f}, {-1.0f}, {-1.0f}}, {0, { 0.5f}, { 0.5f}, {0.5f}},
12535 {D3DCLIP_FRONT, {-0.5f}, {-0.5f}, {-0.5f}}, {0, {-0.5f}, {-0.5f}, {0.0f}}
12537 ok(compare_float(cmp_h[i].hx, out_h[i].hx, 4096)
12538 && compare_float(cmp_h[i].hy, out_h[i].hy, 4096)
12539 && compare_float(cmp_h[i].hz, out_h[i].hz, 4096)
12540 && cmp_h[i].dwFlags == out_h[i].dwFlags,
12541 "HVertex %u differs. Got %#lx %.8e %.8e %.8e.\n", i,
12542 out_h[i].dwFlags, out_h[i].hx, out_h[i].hy, out_h[i].hz);
12544 /* No scheme has been found behind those return values. It seems to be
12545 * whatever data windows has when throwing the vertex away. Modify the
12546 * input test vertices to test this more. Depending on the input data
12547 * it can happen that the z coord gets written into y, or similar things. */
12548 if (0)
12550 static const struct vec4 cmp[] =
12552 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, { -1.0f, -1.0f, 0.5f, 1.0f},
12553 {140.5f, 145.5f, 0.5f, 1.0f}, { -0.5f, -0.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
12555 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12556 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
12557 out[i].x, out[i].y, out[i].z, out[i].w);
12561 transformdata.lpIn = cliptest;
12562 transformdata.dwInSize = sizeof(cliptest[0]);
12563 offscreen = 0xdeadbeef;
12564 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12565 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12566 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12567 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
12568 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12570 static const DWORD flags[] =
12573 D3DCLIP_RIGHT | D3DCLIP_BACK | D3DCLIP_TOP,
12575 D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
12577 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#lx.\n", i, out_h[i].dwFlags);
12580 vp_data = vp_template;
12581 vp_data.dwWidth = 10;
12582 vp_data.dwHeight = 480;
12583 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12584 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
12585 offscreen = 0xdeadbeef;
12586 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12587 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12588 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12589 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
12590 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12592 static const DWORD flags[] =
12594 D3DCLIP_RIGHT,
12595 D3DCLIP_RIGHT | D3DCLIP_BACK,
12596 D3DCLIP_LEFT,
12597 D3DCLIP_LEFT | D3DCLIP_FRONT,
12599 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#lx.\n", i, out_h[i].dwFlags);
12602 vp_data = vp_template;
12603 vp_data.dwWidth = 256;
12604 vp_data.dwHeight = 256;
12605 vp_data.dvScaleX = 1;
12606 vp_data.dvScaleY = 1;
12607 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12608 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
12609 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12610 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12611 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12612 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
12613 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12615 static const DWORD flags[] =
12618 D3DCLIP_BACK,
12620 D3DCLIP_FRONT,
12622 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#lx.\n", i, out_h[i].dwFlags);
12625 /* Finally try to figure out how the DWORD dwOffscreen works.
12626 * It is a logical AND of the vertices' dwFlags members. */
12627 vp_data = vp_template;
12628 vp_data.dwWidth = 5;
12629 vp_data.dwHeight = 5;
12630 vp_data.dvScaleX = 10000.0f;
12631 vp_data.dvScaleY = 10000.0f;
12632 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12633 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
12634 transformdata.lpIn = cliptest;
12635 offscreen = 0xdeadbeef;
12636 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12637 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12638 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12639 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
12641 offscreen = 0xdeadbeef;
12642 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12643 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12644 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12645 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %#lx.\n", offscreen);
12646 offscreen = 0xdeadbeef;
12647 hr = IDirect3DViewport2_TransformVertices(viewport, 2,
12648 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12649 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12650 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %#lx.\n", offscreen);
12651 hr = IDirect3DViewport2_TransformVertices(viewport, 3,
12652 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12653 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12654 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
12656 transformdata.lpIn = cliptest + 1;
12657 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12658 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12659 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12660 ok(offscreen == (D3DCLIP_BACK | D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %#lx.\n", offscreen);
12662 transformdata.lpIn = cliptest + 2;
12663 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12664 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12665 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12666 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %#lx.\n", offscreen);
12667 offscreen = 0xdeadbeef;
12668 hr = IDirect3DViewport2_TransformVertices(viewport, 2,
12669 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12670 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12671 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %#lx.\n", offscreen);
12673 transformdata.lpIn = cliptest + 3;
12674 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12675 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12676 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12677 ok(offscreen == (D3DCLIP_FRONT | D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %#lx.\n", offscreen);
12679 transformdata.lpIn = offscreentest;
12680 transformdata.dwInSize = sizeof(offscreentest[0]);
12681 vp_data = vp_template;
12682 vp_data.dwWidth = 257;
12683 vp_data.dwHeight = 257;
12684 vp_data.dvScaleX = 1.0f;
12685 vp_data.dvScaleY = 1.0f;
12686 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12687 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
12688 offscreen = 0xdeadbeef;
12689 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12690 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12691 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12692 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
12694 vp_data.dwWidth = 256;
12695 vp_data.dwHeight = 256;
12696 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12697 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
12698 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12699 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12700 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12701 ok(offscreen == D3DCLIP_RIGHT, "Offscreen is %#lx.\n", offscreen);
12703 /* Test the effect of Matrices.
12705 * Basically the x coordinate ends up as ((x + 1) * 2 + 0) * 5 and
12706 * y as ((y + 0) * 2 + 1) * 5. The 5 comes from dvScaleX/Y, 2 from
12707 * the view matrix and the +1's from the world and projection matrix. */
12708 vp_data.dwX = 0;
12709 vp_data.dwY = 0;
12710 vp_data.dwWidth = 256;
12711 vp_data.dwHeight = 256;
12712 vp_data.dvScaleX = 5.0f;
12713 vp_data.dvScaleY = 5.0f;
12714 vp_data.dvMinZ = 0.0f;
12715 vp_data.dvMaxZ = 1.0f;
12716 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12717 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
12719 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat_translate1);
12720 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
12721 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat_scale);
12722 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
12723 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat_translate2);
12724 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
12726 transformdata.lpIn = position_tests;
12727 transformdata.dwInSize = sizeof(position_tests[0]);
12728 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12729 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12730 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12732 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12734 static const struct vec4 cmp[] =
12736 {138.0f, 123.0f, 0.0f, 1.0f}, {148.0f, 113.0f, 2.0f, 1.0f}, {128.0f, 133.0f, -2.0f, 1.0f},
12737 {143.0f, 118.0f, 1.0f, 1.0f}, {133.0f, 128.0f, -1.0f, 1.0f}, {133.0f, 128.0f, 0.0f, 1.0f}
12740 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12741 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
12742 out[i].x, out[i].y, out[i].z, out[i].w);
12745 /* Invalid flags. */
12746 offscreen = 0xdeadbeef;
12747 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12748 &transformdata, 0, &offscreen);
12749 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
12750 ok(offscreen == 0xdeadbeef, "Offscreen is %#lx.\n", offscreen);
12752 /* NULL transform data. */
12753 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12754 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
12755 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
12756 ok(offscreen == 0xdeadbeef, "Offscreen is %#lx.\n", offscreen);
12757 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12758 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
12759 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
12760 ok(offscreen == 0xdeadbeef, "Offscreen is %#lx.\n", offscreen);
12762 /* NULL transform data and NULL dwOffscreen.
12764 * Valid transform data + NULL dwOffscreen -> crash. */
12765 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12766 NULL, D3DTRANSFORM_UNCLIPPED, NULL);
12767 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
12769 /* No vertices. */
12770 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12771 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12772 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12773 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
12774 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12775 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12776 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12777 ok(offscreen == ~0u, "Offscreen is %#lx.\n", offscreen);
12779 /* Invalid sizes. */
12780 offscreen = 0xdeadbeef;
12781 transformdata.dwSize = sizeof(transformdata) - 1;
12782 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12783 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12784 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
12785 ok(offscreen == 0xdeadbeef, "Offscreen is %#lx.\n", offscreen);
12786 transformdata.dwSize = sizeof(transformdata) + 1;
12787 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12788 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12789 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
12790 ok(offscreen == 0xdeadbeef, "Offscreen is %#lx.\n", offscreen);
12792 /* NULL lpIn or lpOut -> crash, except when transforming 0 vertices. */
12793 transformdata.dwSize = sizeof(transformdata);
12794 transformdata.lpIn = NULL;
12795 transformdata.lpOut = NULL;
12796 offscreen = 0xdeadbeef;
12797 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12798 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12799 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12800 ok(offscreen == ~0u, "Offscreen is %#lx.\n", offscreen);
12802 /* Test how vertices are transformed during draws. */
12803 vp_data.dwX = 20;
12804 vp_data.dwY = 20;
12805 vp_data.dwWidth = 200;
12806 vp_data.dwHeight = 400;
12807 vp_data.dvScaleX = 20.0f;
12808 vp_data.dvScaleY = 50.0f;
12809 vp_data.dvMinZ = 0.0f;
12810 vp_data.dvMaxZ = 1.0f;
12811 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12812 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
12813 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
12814 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#lx.\n", hr);
12816 ok(SUCCEEDED(hr), "Failed to clear the render target, hr %#lx.\n", hr);
12817 background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 0.0f);
12818 viewport_set_background(device, viewport, background);
12819 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
12820 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
12822 hr = IDirect3DDevice2_BeginScene(device);
12823 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
12824 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
12825 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12826 hr = IDirect3DDevice2_EndScene(device);
12827 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
12829 color = get_surface_color(rt, 128, 143);
12830 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12831 color = get_surface_color(rt, 132, 143);
12832 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12833 color = get_surface_color(rt, 128, 147);
12834 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12835 color = get_surface_color(rt, 132, 147);
12836 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12838 color = get_surface_color(rt, 177, 217);
12839 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12840 color = get_surface_color(rt, 181, 217);
12841 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12842 color = get_surface_color(rt, 177, 221);
12843 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12844 color = get_surface_color(rt, 181, 221);
12845 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12847 /* Test D3DVIEWPORT2 behavior. */
12848 vp2_data.dwSize = sizeof(vp2_data);
12849 vp2_data.dwX = 20;
12850 vp2_data.dwY = 20;
12851 vp2_data.dwWidth = 200;
12852 vp2_data.dwHeight = 400;
12853 vp2_data.dvClipX = -0.5f;
12854 vp2_data.dvClipY = 4.0f;
12855 vp2_data.dvClipWidth = 5.0f;
12856 vp2_data.dvClipHeight = 10.0f;
12857 vp2_data.dvMinZ = 0.0f;
12858 vp2_data.dvMaxZ = 2.0f;
12859 hr = IDirect3DViewport2_SetViewport2(viewport, &vp2_data);
12860 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#lx.\n", hr);
12861 transformdata.lpIn = position_tests;
12862 transformdata.lpOut = out;
12863 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12864 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12865 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12866 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12868 static const struct vec4 cmp[] =
12870 {120.0f, 140.0f, 0.0f, 1.0f}, {200.0f, 60.0f, 1.0f, 1.0f}, {40.0f, 220.0f, -1.0f, 1.0f},
12871 {160.0f, 100.0f, 0.5f, 1.0f}, { 80.0f, 180.0f, -0.5f, 1.0f}, {80.0f, 180.0f, 0.0f, 1.0f}
12874 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12875 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
12876 out[i].x, out[i].y, out[i].z, out[i].w);
12879 memset(&mat, 0, sizeof(mat));
12880 mat.dwSize = sizeof(mat);
12881 mat.diffuse.r = 0.0f;
12882 mat.diffuse.g = 1.0f;
12883 mat.diffuse.b = 0.0f;
12884 mat.diffuse.a = 0.0f;
12885 hr = IDirect3DMaterial2_SetMaterial(background, &mat);
12886 ok(SUCCEEDED(hr), "Failed to set material data, hr %#lx.\n", hr);
12887 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
12888 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
12890 hr = IDirect3DDevice2_BeginScene(device);
12891 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
12892 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
12893 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12894 hr = IDirect3DDevice2_EndScene(device);
12895 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
12897 color = get_surface_color(rt, 58, 118);
12898 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12899 color = get_surface_color(rt, 62, 118);
12900 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12901 color = get_surface_color(rt, 58, 122);
12902 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12903 color = get_surface_color(rt, 62, 122);
12904 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12906 color = get_surface_color(rt, 157, 177);
12907 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12908 color = get_surface_color(rt, 161, 177);
12909 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12910 color = get_surface_color(rt, 157, 181);
12911 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12912 color = get_surface_color(rt, 161, 181);
12913 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12915 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat_identity);
12916 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
12917 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat_identity);
12918 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
12919 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat_transform3);
12920 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
12922 vp2_data.dwX = 0.0;
12923 vp2_data.dwY = 0.0;
12924 vp2_data.dwWidth = 1;
12925 vp2_data.dwHeight = 1;
12926 vp2_data.dvClipX = -12.8f;
12927 vp2_data.dvClipY = 12.8f + mat_transform3._42 / mat_transform3._44;
12928 vp2_data.dvClipWidth = 25.6f;
12929 vp2_data.dvClipHeight = 25.6f;
12930 vp2_data.dvMinZ = 0.0f;
12931 vp2_data.dvMaxZ = 0.5f;
12932 hr = IDirect3DViewport2_SetViewport2(viewport, &vp2_data);
12933 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#lx.\n", hr);
12934 transformdata.lpIn = cliptest;
12935 transformdata.dwInSize = sizeof(cliptest[0]);
12936 offscreen = 0xdeadbeef;
12937 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12938 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12939 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
12940 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
12941 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12943 static const D3DHVERTEX cmp_h[] =
12945 {0, { 25.59f}, { 44.79f}, { 1.0f }},
12946 {D3DCLIP_RIGHT | D3DCLIP_TOP | D3DCLIP_BACK, { 25.61f}, { 44.81f}, { 1.01f}},
12947 {0, {-25.59f}, {-6.39f }, { 0.0f }},
12948 {D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,{-25.61f}, {-6.41f }, {-0.01f}},
12950 ok(compare_float(cmp_h[i].hx, out_h[i].hx, 4096)
12951 && compare_float(cmp_h[i].hy, out_h[i].hy, 4096)
12952 && compare_float(cmp_h[i].hz, out_h[i].hz, 4096)
12953 && cmp_h[i].dwFlags == out_h[i].dwFlags,
12954 "HVertex %u differs. Got %#lx %.8e %.8e %.8e.\n", i,
12955 out_h[i].dwFlags, out_h[i].hx, out_h[i].hy, out_h[i].hz);
12958 IDirectDrawSurface_Release(rt);
12959 destroy_viewport(device, viewport);
12960 IDirect3DMaterial2_Release(background);
12961 refcount = IDirect3DDevice_Release(device);
12962 ok(!refcount, "Device has %lu references left.\n", refcount);
12963 IDirectDraw2_Release(ddraw);
12964 DestroyWindow(window);
12967 static void test_display_mode_surface_pixel_format(void)
12969 unsigned int width, height, bpp;
12970 IDirectDrawSurface *surface;
12971 DDSURFACEDESC surface_desc;
12972 IDirectDraw2 *ddraw;
12973 ULONG refcount;
12974 HWND window;
12975 HRESULT hr;
12977 if (!(ddraw = create_ddraw()))
12979 skip("Failed to create ddraw.\n");
12980 return;
12983 surface_desc.dwSize = sizeof(surface_desc);
12984 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
12985 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#lx.\n", hr);
12986 width = surface_desc.dwWidth;
12987 height = surface_desc.dwHeight;
12989 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
12990 0, 0, width, height, NULL, NULL, NULL, NULL);
12991 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
12992 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
12994 bpp = 0;
12995 if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 16, 0, 0)))
12996 bpp = 16;
12997 if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 24, 0, 0)))
12998 bpp = 24;
12999 if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
13000 bpp = 32;
13001 ok(bpp, "Set display mode failed.\n");
13003 surface_desc.dwSize = sizeof(surface_desc);
13004 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
13005 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#lx.\n", hr);
13006 ok(surface_desc.dwWidth == width, "Got width %lu, expected %u.\n", surface_desc.dwWidth, width);
13007 ok(surface_desc.dwHeight == height, "Got height %lu, expected %u.\n", surface_desc.dwHeight, height);
13008 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == bpp, "Got bpp %lu, expected %u.\n",
13009 surface_desc.ddpfPixelFormat.dwRGBBitCount, bpp);
13011 memset(&surface_desc, 0, sizeof(surface_desc));
13012 surface_desc.dwSize = sizeof(surface_desc);
13013 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
13014 surface_desc.dwBackBufferCount = 1;
13015 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
13016 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13017 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
13018 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
13019 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
13020 ok(surface_desc.dwWidth == width, "Got width %lu, expected %u.\n", surface_desc.dwWidth, width);
13021 ok(surface_desc.dwHeight == height, "Got height %lu, expected %u.\n", surface_desc.dwHeight, height);
13022 ok(surface_desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#lx.\n",
13023 surface_desc.ddpfPixelFormat.dwFlags);
13024 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == bpp, "Got bpp %lu, expected %u.\n",
13025 surface_desc.ddpfPixelFormat.dwRGBBitCount, bpp);
13026 IDirectDrawSurface_Release(surface);
13028 memset(&surface_desc, 0, sizeof(surface_desc));
13029 surface_desc.dwSize = sizeof(surface_desc);
13030 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
13031 surface_desc.dwWidth = width;
13032 surface_desc.dwHeight = height;
13033 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13034 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13035 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
13036 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
13037 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
13038 ok(surface_desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#lx.\n",
13039 surface_desc.ddpfPixelFormat.dwFlags);
13040 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == bpp, "Got bpp %lu, expected %u.\n",
13041 surface_desc.ddpfPixelFormat.dwRGBBitCount, bpp);
13042 IDirectDrawSurface_Release(surface);
13044 refcount = IDirectDraw2_Release(ddraw);
13045 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
13046 DestroyWindow(window);
13049 static void test_surface_desc_size(void)
13051 union
13053 DWORD dwSize;
13054 DDSURFACEDESC desc1;
13055 DDSURFACEDESC2 desc2;
13056 BYTE blob[1024];
13057 } desc;
13058 IDirectDrawSurface7 *surface7;
13059 IDirectDrawSurface2 *surface2;
13060 IDirectDrawSurface *surface;
13061 DDSURFACEDESC surface_desc;
13062 HRESULT expected_hr, hr;
13063 IDirectDraw2 *ddraw;
13064 unsigned int i, j;
13065 ULONG refcount;
13067 static const struct
13069 unsigned int caps;
13070 const char *name;
13072 surface_caps[] =
13074 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
13075 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
13076 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
13078 static const unsigned int desc_sizes[] =
13080 sizeof(DDSURFACEDESC),
13081 sizeof(DDSURFACEDESC2),
13082 sizeof(DDSURFACEDESC) + 1,
13083 sizeof(DDSURFACEDESC2) + 1,
13084 2 * sizeof(DDSURFACEDESC),
13085 2 * sizeof(DDSURFACEDESC2),
13086 sizeof(DDSURFACEDESC) - 1,
13087 sizeof(DDSURFACEDESC2) - 1,
13088 sizeof(DDSURFACEDESC) / 2,
13089 sizeof(DDSURFACEDESC2) / 2,
13093 sizeof(desc) / 2,
13094 sizeof(desc) - 100,
13097 if (!(ddraw = create_ddraw()))
13099 skip("Failed to create ddraw.\n");
13100 return;
13102 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
13103 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
13105 for (i = 0; i < ARRAY_SIZE(surface_caps); ++i)
13107 memset(&surface_desc, 0, sizeof(surface_desc));
13108 surface_desc.dwSize = sizeof(surface_desc);
13109 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
13110 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
13111 surface_desc.dwHeight = 128;
13112 surface_desc.dwWidth = 128;
13113 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
13115 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
13116 continue;
13118 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface2, (void **)&surface2);
13119 ok(hr == DD_OK, "Failed to query IDirectDrawSurface2, hr %#lx, type %s.\n", hr, surface_caps[i].name);
13120 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface7, (void **)&surface7);
13121 ok(hr == DD_OK, "Failed to query IDirectDrawSurface7, hr %#lx, type %s.\n", hr, surface_caps[i].name);
13123 /* GetSurfaceDesc() */
13124 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13126 memset(&desc, 0, sizeof(desc));
13127 desc.dwSize = desc_sizes[j];
13128 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
13129 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
13130 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
13131 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13133 memset(&desc, 0, sizeof(desc));
13134 desc.dwSize = desc_sizes[j];
13135 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
13136 hr = IDirectDrawSurface2_GetSurfaceDesc(surface2, &desc.desc1);
13137 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
13138 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13140 memset(&desc, 0, sizeof(desc));
13141 desc.dwSize = desc_sizes[j];
13142 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
13143 hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
13144 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
13145 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13148 /* Lock() */
13149 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13151 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
13152 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
13153 DWORD expected_texture_stage;
13155 memset(&desc, 0, sizeof(desc));
13156 desc.dwSize = desc_sizes[j];
13157 desc.desc2.dwTextureStage = 0xdeadbeef;
13158 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13159 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
13160 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13161 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
13162 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13163 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %lu, type %s.\n",
13164 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13165 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, size %u, type %s.\n",
13166 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13167 if (SUCCEEDED(hr))
13169 ok(desc.desc1.dwWidth == 128, "Got unexpected width %lu, size %u, type %s.\n",
13170 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
13171 ok(desc.desc1.dwHeight == 128, "Got unexpected height %lu, size %u, type %s.\n",
13172 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
13173 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13174 todo_wine_if(!expected_texture_stage)
13175 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13176 "Got unexpected texture stage %#lx, size %u, type %s.\n",
13177 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13178 IDirectDrawSurface_Unlock(surface, NULL);
13181 memset(&desc, 0, sizeof(desc));
13182 desc.dwSize = desc_sizes[j];
13183 desc.desc2.dwTextureStage = 0xdeadbeef;
13184 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13185 hr = IDirectDrawSurface2_Lock(surface2, NULL, &desc.desc1, 0, 0);
13186 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13187 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
13188 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13189 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %lu, type %s.\n",
13190 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13191 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, size %u, type %s.\n",
13192 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13193 if (SUCCEEDED(hr))
13195 ok(desc.desc2.dwWidth == 128, "Got unexpected width %lu, size %u, type %s.\n",
13196 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
13197 ok(desc.desc2.dwHeight == 128, "Got unexpected height %lu, size %u, type %s.\n",
13198 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
13199 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13200 todo_wine_if(!expected_texture_stage)
13201 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13202 "Got unexpected texture stage %#lx, size %u, type %s.\n",
13203 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13204 IDirectDrawSurface2_Unlock(surface2, NULL);
13207 memset(&desc, 0, sizeof(desc));
13208 desc.dwSize = desc_sizes[j];
13209 desc.desc2.dwTextureStage = 0xdeadbeef;
13210 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13211 hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
13212 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13213 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
13214 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13215 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %lu, type %s.\n",
13216 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13217 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, size %u, type %s.\n",
13218 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13219 if (SUCCEEDED(hr))
13221 ok(desc.desc2.dwWidth == 128, "Got unexpected width %lu, size %u, type %s.\n",
13222 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
13223 ok(desc.desc2.dwHeight == 128, "Got unexpected height %lu, size %u, type %s.\n",
13224 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
13225 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13226 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13227 "Got unexpected texture stage %#lx, size %u, type %s.\n",
13228 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13229 IDirectDrawSurface7_Unlock(surface7, NULL);
13233 IDirectDrawSurface7_Release(surface7);
13234 IDirectDrawSurface2_Release(surface2);
13235 IDirectDrawSurface_Release(surface);
13238 /* GetDisplayMode() */
13239 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13241 memset(&desc, 0xcc, sizeof(desc));
13242 desc.dwSize = desc_sizes[j];
13243 expected_hr = (desc.dwSize == sizeof(DDSURFACEDESC) || desc.dwSize == sizeof(DDSURFACEDESC2))
13244 ? DD_OK : DDERR_INVALIDPARAMS;
13245 hr = IDirectDraw2_GetDisplayMode(ddraw, &desc.desc1);
13246 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u.\n", hr, expected_hr, desc_sizes[j]);
13247 if (SUCCEEDED(hr))
13249 ok(desc.dwSize == sizeof(DDSURFACEDESC), "Wrong size %lu for %u.\n", desc.dwSize, desc_sizes[j]);
13250 ok(desc.blob[desc_sizes[j]] == 0xcc, "Overflow for size %u.\n", desc_sizes[j]);
13251 ok(desc.blob[desc_sizes[j] - 1] != 0xcc, "Struct not cleared for size %u.\n", desc_sizes[j]);
13255 refcount = IDirectDraw2_Release(ddraw);
13256 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
13259 static void test_ck_operation(void)
13261 IDirectDrawSurface2 *src, *dst;
13262 IDirectDrawSurface7 *src7, *dst7;
13263 IDirectDrawSurface *surface1;
13264 DDSURFACEDESC surface_desc;
13265 unsigned int i, *color;
13266 IDirectDraw2 *ddraw;
13267 ULONG refcount;
13268 HWND window;
13269 HRESULT hr;
13270 DDCOLORKEY ckey;
13271 DDBLTFX fx;
13273 window = create_window();
13274 ddraw = create_ddraw();
13275 ok(!!ddraw, "Failed to create a ddraw object.\n");
13276 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13277 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
13279 memset(&surface_desc, 0, sizeof(surface_desc));
13280 surface_desc.dwSize = sizeof(surface_desc);
13281 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13282 surface_desc.dwWidth = 4;
13283 surface_desc.dwHeight = 1;
13284 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13285 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
13286 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
13287 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
13288 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
13289 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
13290 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
13291 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
13292 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&dst);
13293 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#lx.\n", hr);
13294 IDirectDrawSurface_Release(surface1);
13296 surface_desc.dwFlags |= DDSD_CKSRCBLT;
13297 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
13298 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff;
13299 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
13300 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
13301 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&src);
13302 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#lx.\n", hr);
13303 IDirectDrawSurface_Release(surface1);
13305 hr = IDirectDrawSurface2_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13306 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13307 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
13308 color = surface_desc.lpSurface;
13309 color[0] = 0x77010203;
13310 color[1] = 0x00010203;
13311 color[2] = 0x77ff00ff;
13312 color[3] = 0x00ff00ff;
13313 hr = IDirectDrawSurface2_Unlock(src, NULL);
13314 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13316 for (i = 0; i < 2; ++i)
13318 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13319 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13320 color = surface_desc.lpSurface;
13321 color[0] = 0xcccccccc;
13322 color[1] = 0xcccccccc;
13323 color[2] = 0xcccccccc;
13324 color[3] = 0xcccccccc;
13325 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13326 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13328 if (i)
13330 hr = IDirectDrawSurface2_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY);
13331 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
13333 else
13335 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL);
13336 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
13339 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL);
13340 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13341 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
13342 color = surface_desc.lpSurface;
13343 /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
13344 * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for
13345 * color keying, but do not copy it into the destination surface. Nvidia neither uses it for
13346 * color keying nor copies it. */
13347 ok((color[0] == 0x77010203 && color[1] == 0x00010203
13348 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */
13349 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
13350 && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */
13351 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
13352 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */
13353 || broken(color[0] == 0xff010203 && color[1] == 0xff010203
13354 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */,
13355 "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n",
13356 color[0], color[1], color[2], color[3], i);
13357 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13358 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13361 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13362 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
13363 ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff,
13364 "Got unexpected color key low=%08lx high=%08lx.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13366 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
13367 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13368 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
13370 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13371 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13372 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
13373 ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00,
13374 "Got unexpected color key low=%08lx high=%08lx.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13376 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
13377 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
13378 hr = IDirectDrawSurface2_GetSurfaceDesc(src, &surface_desc);
13379 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
13380 ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00
13381 && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00,
13382 "Got unexpected color key low=%08lx high=%08lx.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
13383 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
13385 /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
13386 ckey.dwColorSpaceLowValue = 0x000000ff;
13387 ckey.dwColorSpaceHighValue = 0x00000000;
13388 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13389 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
13391 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13392 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13393 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
13394 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
13395 "Got unexpected color key low=%08lx high=%08lx.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13397 ckey.dwColorSpaceLowValue = 0x000000ff;
13398 ckey.dwColorSpaceHighValue = 0x00000001;
13399 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13400 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
13402 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13403 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13404 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
13405 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
13406 "Got unexpected color key low=%08lx high=%08lx.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13408 ckey.dwColorSpaceLowValue = 0x000000fe;
13409 ckey.dwColorSpaceHighValue = 0x000000fd;
13410 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13411 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
13413 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13414 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13415 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
13416 ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe,
13417 "Got unexpected color key low=%08lx high=%08lx.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13419 IDirectDrawSurface2_Release(src);
13420 IDirectDrawSurface2_Release(dst);
13422 /* Test source and destination keys and where they are read from. Use a surface with alpha
13423 * to avoid driver-dependent content in the X channel. */
13424 memset(&surface_desc, 0, sizeof(surface_desc));
13425 surface_desc.dwSize = sizeof(surface_desc);
13426 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13427 surface_desc.dwWidth = 6;
13428 surface_desc.dwHeight = 1;
13429 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13430 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
13431 surface_desc.ddpfPixelFormat.dwRGBBitCount = 32;
13432 surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
13433 surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
13434 surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
13435 surface_desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
13436 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
13437 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
13438 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&dst);
13439 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#lx.\n", hr);
13440 IDirectDrawSurface_Release(surface1);
13442 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
13443 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
13444 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&src);
13445 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#lx.\n", hr);
13446 IDirectDrawSurface_Release(surface1);
13448 ckey.dwColorSpaceLowValue = 0x0000ff00;
13449 ckey.dwColorSpaceHighValue = 0x0000ff00;
13450 hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
13451 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
13452 ckey.dwColorSpaceLowValue = 0x00ff0000;
13453 ckey.dwColorSpaceHighValue = 0x00ff0000;
13454 hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_DESTBLT, &ckey);
13455 ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#lx.\n", hr);
13456 if (FAILED(hr))
13458 /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */
13459 skip("Failed to set destination color key, skipping related tests.\n");
13460 goto done;
13463 ckey.dwColorSpaceLowValue = 0x000000ff;
13464 ckey.dwColorSpaceHighValue = 0x000000ff;
13465 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13466 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
13467 ckey.dwColorSpaceLowValue = 0x000000aa;
13468 ckey.dwColorSpaceHighValue = 0x000000aa;
13469 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_DESTBLT, &ckey);
13470 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
13472 memset(&fx, 0, sizeof(fx));
13473 fx.dwSize = sizeof(fx);
13474 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000;
13475 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000;
13476 fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100;
13477 fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100;
13479 hr = IDirectDrawSurface2_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13480 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13481 color = surface_desc.lpSurface;
13482 color[0] = 0x000000ff; /* Applies to src blt key in src surface. */
13483 color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */
13484 color[2] = 0x00ff0000; /* Dst color key in dst surface. */
13485 color[3] = 0x0000ff00; /* Src color key in dst surface. */
13486 color[4] = 0x00001100; /* Src color key in ddbltfx. */
13487 color[5] = 0x00110000; /* Dst color key in ddbltfx. */
13488 hr = IDirectDrawSurface2_Unlock(src, NULL);
13489 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13491 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13492 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13493 color = surface_desc.lpSurface;
13494 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13495 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13496 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13498 /* Test a blit without keying. */
13499 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, 0, &fx);
13500 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
13502 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13503 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13504 color = surface_desc.lpSurface;
13505 /* Should have copied src data unmodified to dst. */
13506 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13507 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13508 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13509 color[0], color[1], color[2], color[3], color[4], color[5]);
13511 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13512 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13513 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13515 /* Src key. */
13516 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
13517 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
13519 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13520 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13521 color = surface_desc.lpSurface;
13522 /* Src key applied to color[0]. It is unmodified, the others are copied. */
13523 ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13524 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13525 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13526 color[0], color[1], color[2], color[3], color[4], color[5]);
13528 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13529 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13530 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13532 /* Src override. */
13533 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
13534 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
13536 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13537 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13538 color = surface_desc.lpSurface;
13539 /* Override key applied to color[5]. It is unmodified, the others are copied. */
13540 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13541 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555,
13542 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13543 color[0], color[1], color[2], color[3], color[4], color[5]);
13545 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13546 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13547 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13549 /* Src override AND src key. That is not supposed to work. */
13550 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
13551 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13553 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13554 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13555 color = surface_desc.lpSurface;
13556 /* Ensure the destination was not changed. */
13557 ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 &&
13558 color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555,
13559 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13560 color[0], color[1], color[2], color[3], color[4], color[5]);
13562 /* Use different dst colors for the dst key test. */
13563 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13564 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13565 color[2] = 0x00001100; /* Dest key in override. */
13566 color[3] = 0x00001100; /* Dest key in override. */
13567 color[4] = 0x000000aa; /* Dest key in src surface. */
13568 color[5] = 0x000000aa; /* Dest key in src surface. */
13569 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13570 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13572 /* Dest key blit. The key is taken from the SOURCE surface in v2! */
13573 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13574 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
13576 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13577 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13578 color = surface_desc.lpSurface;
13579 /* Dst key applied to color[4,5], they are the only changed pixels. */
13580 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13581 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
13582 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13583 color[0], color[1], color[2], color[3], color[4], color[5]);
13585 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13586 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13587 color[2] = 0x00001100; /* Dest key in override. */
13588 color[3] = 0x00001100; /* Dest key in override. */
13589 color[4] = 0x000000aa; /* Dest key in src surface. */
13590 color[5] = 0x000000aa; /* Dest key in src surface. */
13591 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13592 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13594 /* What happens with a QI'd newer version of the interface? It takes the key
13595 * from the destination surface. */
13596 hr = IDirectDrawSurface2_QueryInterface(src, &IID_IDirectDrawSurface7, (void **)&src7);
13597 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#lx.\n", hr);
13598 hr = IDirectDrawSurface2_QueryInterface(dst, &IID_IDirectDrawSurface7, (void **)&dst7);
13599 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#lx.\n", hr);
13601 hr = IDirectDrawSurface7_Blt(dst7, NULL, src7, NULL, DDBLT_KEYDEST, &fx);
13602 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
13604 IDirectDrawSurface7_Release(dst7);
13605 IDirectDrawSurface7_Release(src7);
13607 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13608 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13609 color = surface_desc.lpSurface;
13610 /* Dst key applied to color[0,1], they are the only changed pixels. */
13611 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
13612 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13613 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13614 color[0], color[1], color[2], color[3], color[4], color[5]);
13616 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13617 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13618 color[2] = 0x00001100; /* Dest key in override. */
13619 color[3] = 0x00001100; /* Dest key in override. */
13620 color[4] = 0x000000aa; /* Dest key in src surface. */
13621 color[5] = 0x000000aa; /* Dest key in src surface. */
13622 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13623 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13625 /* Dest override key blit. */
13626 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
13627 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
13629 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13630 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13631 color = surface_desc.lpSurface;
13632 /* Dst key applied to color[2,3], they are the only changed pixels. */
13633 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 &&
13634 color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13635 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13636 color[0], color[1], color[2], color[3], color[4], color[5]);
13638 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13639 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13640 color[2] = 0x00001100; /* Dest key in override. */
13641 color[3] = 0x00001100; /* Dest key in override. */
13642 color[4] = 0x000000aa; /* Dest key in src surface. */
13643 color[5] = 0x000000aa; /* Dest key in src surface. */
13644 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13645 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13647 /* Dest override together with surface key. Supposed to fail. */
13648 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
13649 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13651 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13652 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13653 color = surface_desc.lpSurface;
13654 /* Destination is unchanged. */
13655 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13656 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13657 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13658 color[0], color[1], color[2], color[3], color[4], color[5]);
13659 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13660 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13662 /* Source and destination key. This is driver dependent. New HW treats it like
13663 * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */
13664 if (0)
13666 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
13667 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
13669 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13670 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13671 color = surface_desc.lpSurface;
13672 /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if
13673 * the driver applies it. */
13674 ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13675 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13676 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13677 color[0], color[1], color[2], color[3], color[4], color[5]);
13679 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13680 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13681 color[2] = 0x00001100; /* Dest key in override. */
13682 color[3] = 0x00001100; /* Dest key in override. */
13683 color[4] = 0x000000aa; /* Dest key in src surface. */
13684 color[5] = 0x000000aa; /* Dest key in src surface. */
13685 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13686 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13689 /* Override keys without ddbltfx parameter fail */
13690 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
13691 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13692 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
13693 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13695 /* Try blitting without keys in the source surface. */
13696 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, NULL);
13697 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
13698 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_DESTBLT, NULL);
13699 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
13701 /* That fails now. Do not bother to check that the data is unmodified. */
13702 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
13703 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13705 /* Surprisingly this still works. It uses the old key from the src surface. */
13706 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13707 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
13709 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13710 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13711 color = surface_desc.lpSurface;
13712 /* Dst key applied to color[4,5], they are the only changed pixels. */
13713 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13714 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
13715 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13716 color[0], color[1], color[2], color[3], color[4], color[5]);
13717 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13718 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13720 /* This returns DDERR_NOCOLORKEY as expected. */
13721 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_DESTBLT, &ckey);
13722 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx.\n", hr);
13724 /* GetSurfaceDesc returns a zeroed key as expected. */
13725 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x12345678;
13726 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x12345678;
13727 hr = IDirectDrawSurface2_GetSurfaceDesc(src, &surface_desc);
13728 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
13729 ok(!surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue
13730 && !surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue,
13731 "Got unexpected color key low=%08lx high=%08lx.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
13732 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
13734 /* Try blitting without keys in the destination surface. */
13735 hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_SRCBLT, NULL);
13736 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
13737 hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_DESTBLT, NULL);
13738 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
13740 /* This fails, as sanity would dictate. */
13741 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13742 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13744 done:
13745 IDirectDrawSurface2_Release(src);
13746 IDirectDrawSurface2_Release(dst);
13747 refcount = IDirectDraw2_Release(ddraw);
13748 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
13749 DestroyWindow(window);
13752 static void test_set_render_state(void)
13754 IDirect3DDevice2 *device;
13755 IDirectDraw2 *ddraw;
13756 ULONG refcount;
13757 HWND window;
13758 DWORD state;
13759 HRESULT hr;
13761 window = create_window();
13762 ddraw = create_ddraw();
13763 ok(!!ddraw, "Failed to create a ddraw object.\n");
13764 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
13766 skip("Failed to create 3D device.\n");
13767 DestroyWindow(window);
13768 return;
13771 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, TRUE);
13772 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13773 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, FALSE);
13774 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13776 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
13777 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13778 state = 0xdeadbeef;
13779 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, &state);
13780 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13781 ok(!state, "Got unexpected render state %#lx.\n", state);
13782 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
13783 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13784 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, &state);
13785 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13786 ok(state == D3DTBLEND_MODULATE, "Got unexpected render state %#lx.\n", state);
13788 refcount = IDirect3DDevice2_Release(device);
13789 ok(!refcount, "Device has %lu references left.\n", refcount);
13790 refcount = IDirectDraw2_Release(ddraw);
13791 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
13792 DestroyWindow(window);
13795 static void test_depth_readback(void)
13797 unsigned int depth, expected_depth, i, x, y, max_diff, passed_fmts = 0;
13798 IDirect3DMaterial2 *blue_background;
13799 IDirectDrawSurface *rt, *ds;
13800 IDirect3DViewport2 *viewport;
13801 DDSURFACEDESC surface_desc;
13802 IDirect3DDevice2 *device;
13803 IDirectDraw2 *ddraw;
13804 ULONG refcount;
13805 HWND window;
13806 HRESULT hr;
13807 void *ptr;
13808 BOOL all_pass;
13810 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
13811 static D3DLVERTEX quad[] =
13813 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0xff00ff00}},
13814 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
13815 {{ 1.0f}, {-1.0f}, {1.0f}, 0, {0xff00ff00}},
13816 {{ 1.0f}, { 1.0f}, {0.9f}, 0, {0xff00ff00}},
13819 static const struct
13821 unsigned int z_depth, z_mask;
13823 tests[] =
13825 {16, 0x0000ffff},
13826 {24, 0x00ffffff},
13827 {32, 0xffffffff},
13830 window = create_window();
13831 ok(!!window, "Failed to create a window.\n");
13832 ddraw = create_ddraw();
13833 ok(!!ddraw, "Failed to create a ddraw object.\n");
13834 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
13836 skip("Failed to create a D3D device, skipping tests.\n");
13837 IDirectDraw2_Release(ddraw);
13838 DestroyWindow(window);
13839 return;
13842 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
13843 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
13844 blue_background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
13845 viewport = create_viewport(device, 0, 0, 640, 480);
13846 viewport_set_background(device, viewport, blue_background);
13847 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
13848 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
13850 ds = get_depth_stencil(device);
13851 hr = IDirectDrawSurface_DeleteAttachedSurface(rt, 0, ds);
13852 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#lx.\n", hr);
13853 IDirectDrawSurface_Release(ds);
13855 for (i = 0; i < ARRAY_SIZE(tests); ++i)
13857 memset(&surface_desc, 0, sizeof(surface_desc));
13858 surface_desc.dwSize = sizeof(surface_desc);
13859 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
13860 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
13861 surface_desc.dwZBufferBitDepth = tests[i].z_depth;
13862 surface_desc.dwWidth = 640;
13863 surface_desc.dwHeight = 480;
13864 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
13865 if (FAILED(hr))
13867 skip("Format %u not supported, skipping test.\n", i);
13868 continue;
13871 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
13872 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#lx.\n", hr);
13873 hr = IDirect3DDevice2_SetRenderTarget(device, rt, 0);
13874 ok(SUCCEEDED(hr), "Failed to set render target, hr %#lx.\n", hr);
13876 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
13877 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
13878 hr = IDirect3DDevice2_BeginScene(device);
13879 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
13880 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
13881 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
13882 hr = IDirect3DDevice2_EndScene(device);
13883 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
13885 memset(&surface_desc, 0, sizeof(surface_desc));
13886 surface_desc.dwSize = sizeof(surface_desc);
13887 hr = IDirectDrawSurface_Lock(ds, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13888 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
13890 all_pass = TRUE;
13891 for (y = 60; y < 480; y += 120)
13893 for (x = 80; x < 640; x += 160)
13895 ptr = (BYTE *)surface_desc.lpSurface
13896 + y * surface_desc.lPitch
13897 + x * (tests[i].z_depth == 16 ? 2 : 4);
13898 depth = *((DWORD *)ptr) & tests[i].z_mask;
13899 expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
13900 max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
13901 /* The ddraw2 version of this test behaves similarly to the ddraw7 version on Nvidia GPUs,
13902 * except that we only have D16 (broken on geforce 9) and D24X8 (broken on geforce 7) available.
13903 * Accept all nvidia GPUs as broken here, but still expect one of the formats to pass. */
13904 ok(compare_uint(expected_depth, depth, max_diff) || ddraw_is_nvidia(ddraw)
13905 || (ddraw_is_amd(ddraw) && tests[i].z_depth == 24),
13906 "Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
13907 i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
13908 if (!compare_uint(expected_depth, depth, max_diff))
13909 all_pass = FALSE;
13913 hr = IDirectDrawSurface_Unlock(ds, NULL);
13914 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13916 if (all_pass)
13917 passed_fmts++;
13919 hr = IDirectDrawSurface_DeleteAttachedSurface(rt, 0, ds);
13920 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#lx.\n", hr);
13921 IDirectDrawSurface_Release(ds);
13924 ok(passed_fmts, "Not a single format passed the tests, this is bad even by Nvidia's standards.\n");
13926 destroy_viewport(device, viewport);
13927 destroy_material(blue_background);
13928 IDirectDrawSurface_Release(rt);
13929 refcount = IDirect3DDevice2_Release(device);
13930 ok(!refcount, "Device has %lu references left.\n", refcount);
13931 IDirectDraw2_Release(ddraw);
13932 DestroyWindow(window);
13935 static void test_clear(void)
13937 D3DRECT rect_negneg, rect_full = {{0}, {0}, {640}, {480}};
13938 IDirect3DViewport2 *viewport, *viewport2, *viewport3;
13939 IDirect3DMaterial2 *white, *red, *green, *blue;
13940 IDirect3DDevice2 *device;
13941 IDirectDrawSurface *rt;
13942 IDirectDraw2 *ddraw;
13943 unsigned int color;
13944 D3DRECT rect[2];
13945 ULONG refcount;
13946 HWND window;
13947 HRESULT hr;
13949 window = create_window();
13950 ddraw = create_ddraw();
13951 ok(!!ddraw, "Failed to create a ddraw object.\n");
13952 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
13954 skip("Failed to create a 3D device, skipping test.\n");
13955 IDirectDraw2_Release(ddraw);
13956 DestroyWindow(window);
13957 return;
13959 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
13960 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
13962 viewport = create_viewport(device, 0, 0, 640, 480);
13963 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
13964 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
13966 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
13967 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
13968 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
13969 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
13971 viewport_set_background(device, viewport, white);
13972 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
13973 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
13975 /* Positive x, negative y. */
13976 rect[0].x1 = 0;
13977 rect[0].y1 = 480;
13978 rect[0].x2 = 320;
13979 rect[0].y2 = 240;
13981 /* Positive x, positive y. */
13982 rect[1].x1 = 0;
13983 rect[1].y1 = 0;
13984 rect[1].x2 = 320;
13985 rect[1].y2 = 240;
13987 /* Clear 2 rectangles with one call. Unlike d3d8/9, the refrast does not
13988 * refuse negative rectangles, but it will not clear them either. */
13989 viewport_set_background(device, viewport, red);
13990 hr = IDirect3DViewport2_Clear(viewport, 2, rect, D3DCLEAR_TARGET);
13991 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
13993 color = get_surface_color(rt, 160, 360);
13994 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 3 (pos, neg) has color 0x%08x.\n", color);
13995 color = get_surface_color(rt, 160, 120);
13996 ok(compare_color(color, 0x00ff0000, 0), "Clear rectangle 1 (pos, pos) has color 0x%08x.\n", color);
13997 color = get_surface_color(rt, 480, 360);
13998 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (NULL) has color 0x%08x.\n", color);
13999 color = get_surface_color(rt, 480, 120);
14000 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (neg, neg) has color 0x%08x.\n", color);
14002 viewport_set_background(device, viewport, white);
14003 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
14004 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
14006 /* negative x, negative y.
14007 * Also ignored, except on WARP, which clears the entire screen. */
14008 rect_negneg.x1 = 640;
14009 rect_negneg.y1 = 240;
14010 rect_negneg.x2 = 320;
14011 rect_negneg.y2 = 0;
14012 viewport_set_background(device, viewport, green);
14013 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_negneg, D3DCLEAR_TARGET);
14014 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
14016 color = get_surface_color(rt, 160, 360);
14017 ok(compare_color(color, 0x00ffffff, 0)
14018 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14019 "Got unexpected color 0x%08x.\n", color);
14020 color = get_surface_color(rt, 160, 120);
14021 ok(compare_color(color, 0x00ffffff, 0)
14022 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14023 "Got unexpected color 0x%08x.\n", color);
14024 color = get_surface_color(rt, 480, 360);
14025 ok(compare_color(color, 0x00ffffff, 0)
14026 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14027 "Got unexpected color 0x%08x.\n", color);
14028 color = get_surface_color(rt, 480, 120);
14029 ok(compare_color(color, 0x00ffffff, 0)
14030 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14031 "Got unexpected color 0x%08x.\n", color);
14033 /* Test how the viewport affects clears. */
14034 viewport_set_background(device, viewport, white);
14035 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
14036 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
14038 viewport2 = create_viewport(device, 160, 120, 160, 120);
14039 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
14040 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
14042 viewport_set_background(device, viewport2, blue);
14043 hr = IDirect3DViewport2_Clear(viewport2, 1, &rect_full, D3DCLEAR_TARGET);
14044 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
14046 viewport3 = create_viewport(device, 320, 240, 320, 240);
14047 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport3);
14048 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
14050 rect[0].x1 = 160;
14051 rect[0].y1 = 120;
14052 rect[0].x2 = 480;
14053 rect[0].y2 = 360;
14054 viewport_set_background(device, viewport3, green);
14055 hr = IDirect3DViewport2_Clear(viewport3, 1, &rect[0], D3DCLEAR_TARGET);
14056 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
14058 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
14059 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
14061 color = get_surface_color(rt, 158, 118);
14062 ok(compare_color(color, 0x00ffffff, 0), "(158, 118) has color 0x%08x.\n", color);
14063 color = get_surface_color(rt, 162, 118);
14064 ok(compare_color(color, 0x00ffffff, 0), "(162, 118) has color 0x%08x.\n", color);
14065 color = get_surface_color(rt, 158, 122);
14066 ok(compare_color(color, 0x00ffffff, 0), "(158, 122) has color 0x%08x.\n", color);
14067 color = get_surface_color(rt, 162, 122);
14068 ok(compare_color(color, 0x000000ff, 0), "(162, 122) has color 0x%08x.\n", color);
14070 color = get_surface_color(rt, 318, 238);
14071 ok(compare_color(color, 0x000000ff, 0), "(318, 238) has color 0x%08x.\n", color);
14072 color = get_surface_color(rt, 322, 238);
14073 ok(compare_color(color, 0x00ffffff, 0), "(322, 238) has color 0x%08x.\n", color);
14074 color = get_surface_color(rt, 318, 242);
14075 ok(compare_color(color, 0x00ffffff, 0), "(318, 242) has color 0x%08x.\n", color);
14076 color = get_surface_color(rt, 322, 242);
14077 ok(compare_color(color, 0x0000ff00, 0), "(322, 242) has color 0x%08x.\n", color);
14079 color = get_surface_color(rt, 478, 358);
14080 ok(compare_color(color, 0x0000ff00, 0), "(478, 358) has color 0x%08x.\n", color);
14081 color = get_surface_color(rt, 482, 358);
14082 ok(compare_color(color, 0x00ffffff, 0), "(482, 358) has color 0x%08x.\n", color);
14083 color = get_surface_color(rt, 478, 362);
14084 ok(compare_color(color, 0x00ffffff, 0), "(478, 362) has color 0x%08x.\n", color);
14085 color = get_surface_color(rt, 482, 362);
14086 ok(compare_color(color, 0x00ffffff, 0), "(482, 362) has color 0x%08x.\n", color);
14088 /* The clear rectangle is rendertarget absolute, not relative to the
14089 * viewport. */
14090 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
14091 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
14092 rect[0].x1 = 330;
14093 rect[0].y1 = 250;
14094 rect[0].x2 = 340;
14095 rect[0].y2 = 260;
14096 hr = IDirect3DViewport2_Clear(viewport3, 1, &rect[0], D3DCLEAR_TARGET);
14097 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
14099 color = get_surface_color(rt, 328, 248);
14100 ok(compare_color(color, 0x00ffffff, 0), "(328, 248) has color 0x%08x.\n", color);
14101 color = get_surface_color(rt, 332, 248);
14102 ok(compare_color(color, 0x00ffffff, 0), "(332, 248) has color 0x%08x.\n", color);
14103 color = get_surface_color(rt, 328, 252);
14104 ok(compare_color(color, 0x00ffffff, 0), "(328, 252) has color 0x%08x.\n", color);
14105 color = get_surface_color(rt, 332, 252);
14106 ok(compare_color(color, 0x0000ff00, 0), "(332, 252) has color 0x%08x.\n", color);
14108 color = get_surface_color(rt, 338, 248);
14109 ok(compare_color(color, 0x00ffffff, 0), "(338, 248) has color 0x%08x.\n", color);
14110 color = get_surface_color(rt, 342, 248);
14111 ok(compare_color(color, 0x00ffffff, 0), "(342, 248) has color 0x%08x.\n", color);
14112 color = get_surface_color(rt, 338, 252);
14113 ok(compare_color(color, 0x0000ff00, 0), "(338, 252) has color 0x%08x.\n", color);
14114 color = get_surface_color(rt, 342, 252);
14115 ok(compare_color(color, 0x00ffffff, 0), "(342, 252) has color 0x%08x.\n", color);
14117 color = get_surface_color(rt, 328, 258);
14118 ok(compare_color(color, 0x00ffffff, 0), "(328, 258) has color 0x%08x.\n", color);
14119 color = get_surface_color(rt, 332, 258);
14120 ok(compare_color(color, 0x0000ff00, 0), "(332, 258) has color 0x%08x.\n", color);
14121 color = get_surface_color(rt, 328, 262);
14122 ok(compare_color(color, 0x00ffffff, 0), "(328, 262) has color 0x%08x.\n", color);
14123 color = get_surface_color(rt, 332, 262);
14124 ok(compare_color(color, 0x00ffffff, 0), "(332, 262) has color 0x%08x.\n", color);
14126 color = get_surface_color(rt, 338, 258);
14127 ok(compare_color(color, 0x0000ff00, 0), "(338, 258) has color 0x%08x.\n", color);
14128 color = get_surface_color(rt, 342, 258);
14129 ok(compare_color(color, 0x00ffffff, 0), "(342, 258) has color 0x%08x.\n", color);
14130 color = get_surface_color(rt, 338, 262);
14131 ok(compare_color(color, 0x00ffffff, 0), "(338, 262) has color 0x%08x.\n", color);
14132 color = get_surface_color(rt, 342, 262);
14133 ok(compare_color(color, 0x00ffffff, 0), "(342, 262) has color 0x%08x.\n", color);
14135 /* COLORWRITEENABLE, SRGBWRITEENABLE and scissor rectangles do not exist
14136 * in d3d2. */
14138 IDirect3DViewport2_Release(viewport3);
14139 IDirect3DViewport2_Release(viewport2);
14140 IDirect3DViewport2_Release(viewport);
14141 IDirect3DMaterial2_Release(white);
14142 IDirect3DMaterial2_Release(red);
14143 IDirect3DMaterial2_Release(green);
14144 IDirect3DMaterial2_Release(blue);
14145 IDirectDrawSurface_Release(rt);
14146 refcount = IDirect3DDevice2_Release(device);
14147 ok(!refcount, "Device has %lu references left.\n", refcount);
14148 refcount = IDirectDraw2_Release(ddraw);
14149 ok(!refcount, "Ddraw object has %lu references left.\n", refcount);
14150 DestroyWindow(window);
14153 struct enum_surfaces_param
14155 IDirectDraw2 *ddraw;
14156 DDSURFACEDESC modes[20];
14157 unsigned int mode_count;
14159 IDirectDrawSurface *surfaces[8];
14160 unsigned int count;
14163 static HRESULT CALLBACK build_mode_list_cb(DDSURFACEDESC *desc, void *context)
14165 struct enum_surfaces_param *param = context;
14166 IDirectDrawSurface *surface;
14168 if (SUCCEEDED(IDirectDraw2_CreateSurface(param->ddraw, desc, &surface, NULL)))
14170 if (param->mode_count < ARRAY_SIZE(param->modes))
14171 param->modes[param->mode_count] = *desc;
14172 ++param->mode_count;
14173 IDirectDrawSurface_Release(surface);
14176 return DDENUMRET_OK;
14179 static HRESULT WINAPI enum_surfaces_cb(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
14181 struct enum_surfaces_param *param = context;
14182 BOOL found = FALSE;
14183 unsigned int i;
14185 for (i = 0; i < ARRAY_SIZE(param->surfaces); ++i)
14187 if (param->surfaces[i] == surface)
14189 found = TRUE;
14190 break;
14194 ok(found, "Unexpected surface %p enumerated.\n", surface);
14195 IDirectDrawSurface_Release(surface);
14196 ++param->count;
14198 return DDENUMRET_OK;
14201 static HRESULT WINAPI enum_surfaces_create_cb(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
14203 static const DWORD expect_flags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_PIXELFORMAT;
14204 struct enum_surfaces_param *param = context;
14206 ok(!surface, "Unexpected surface %p.\n", surface);
14207 ok((desc->dwFlags & expect_flags) == expect_flags, "Got unexpected flags %#lx.\n", desc->dwFlags);
14208 if (param->count < ARRAY_SIZE(param->modes))
14210 const DDSURFACEDESC *expect = &param->modes[param->count];
14211 ok(desc->dwWidth == expect->dwWidth, "Expected width %lu, got %lu.\n", expect->dwWidth, desc->dwWidth);
14212 ok(desc->dwHeight == expect->dwHeight, "Expected height %lu, got %lu.\n", expect->dwHeight, desc->dwHeight);
14213 ok(!memcmp(&desc->ddpfPixelFormat, &expect->ddpfPixelFormat, sizeof(desc->ddpfPixelFormat)),
14214 "Pixel formats didn't match.\n");
14217 ++param->count;
14219 return DDENUMRET_OK;
14222 static void test_enum_surfaces(void)
14224 struct enum_surfaces_param param = {0};
14225 DDPIXELFORMAT current_format;
14226 IDirectDraw2 *ddraw;
14227 DDSURFACEDESC desc;
14228 HRESULT hr;
14230 ddraw = create_ddraw();
14231 ok(!!ddraw, "Failed to create a ddraw object.\n");
14232 param.ddraw = ddraw;
14234 memset(&desc, 0, sizeof(desc));
14235 desc.dwSize = sizeof(desc);
14236 hr = IDirectDraw2_GetDisplayMode(ddraw, &desc);
14237 ok(hr == DD_OK, "Failed to get display mode, hr %#lx.\n", hr);
14238 current_format = desc.ddpfPixelFormat;
14240 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
14241 ok(hr == DD_OK, "Failed to set cooperative level, hr %#lx.\n", hr);
14243 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_ALL, NULL, NULL, enum_surfaces_cb);
14244 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
14246 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_ALL,
14247 NULL, NULL, enum_surfaces_cb);
14248 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
14250 memset(&desc, 0, sizeof(desc));
14251 desc.dwSize = sizeof(desc);
14252 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
14253 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
14254 desc.dwMipMapCount = 3;
14255 desc.dwWidth = 32;
14256 desc.dwHeight = 32;
14257 hr = IDirectDraw2_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL);
14258 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#lx.\n", hr);
14260 hr = IDirectDrawSurface_GetAttachedSurface(param.surfaces[0], &desc.ddsCaps, &param.surfaces[1]);
14261 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#lx.\n", hr);
14262 hr = IDirectDrawSurface_GetAttachedSurface(param.surfaces[1], &desc.ddsCaps, &param.surfaces[2]);
14263 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#lx.\n", hr);
14264 hr = IDirectDrawSurface_GetAttachedSurface(param.surfaces[2], &desc.ddsCaps, &param.surfaces[3]);
14265 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
14266 ok(!param.surfaces[3], "Got unexpected pointer %p.\n", param.surfaces[3]);
14268 param.count = 0;
14269 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
14270 &desc, &param, enum_surfaces_cb);
14271 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#lx.\n", hr);
14272 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14274 param.count = 0;
14275 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
14276 NULL, &param, enum_surfaces_cb);
14277 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#lx.\n", hr);
14278 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14280 desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
14281 param.count = 0;
14282 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
14283 &desc, &param, enum_surfaces_cb);
14284 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
14285 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14287 param.count = 0;
14288 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_NOMATCH,
14289 &desc, &param, enum_surfaces_cb);
14290 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
14291 ok(param.count == 2, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14293 desc.dwFlags = 0;
14294 param.count = 0;
14295 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
14296 &desc, &param, enum_surfaces_cb);
14297 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
14298 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14300 desc.dwFlags = 0;
14301 param.count = 0;
14302 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST, &desc, &param, enum_surfaces_cb);
14303 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
14304 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14306 IDirectDrawSurface_Release(param.surfaces[2]);
14307 IDirectDrawSurface_Release(param.surfaces[1]);
14308 IDirectDrawSurface_Release(param.surfaces[0]);
14310 param.count = 0;
14311 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
14312 NULL, &param, enum_surfaces_cb);
14313 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
14314 ok(!param.count, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14316 memset(&desc, 0, sizeof(desc));
14317 desc.dwSize = sizeof(desc);
14318 desc.dwFlags = DDSD_CAPS;
14319 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
14321 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_ALL,
14322 &desc, &param, enum_surfaces_create_cb);
14323 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#lx.\n", hr);
14325 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_NOMATCH,
14326 &desc, &param, enum_surfaces_create_cb);
14327 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#lx.\n", hr);
14329 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED,
14330 &desc, &param, enum_surfaces_create_cb);
14331 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#lx.\n", hr);
14333 /* When not passed width and height, the callback is called with every
14334 * available display resolution. */
14336 param.mode_count = 0;
14337 desc.dwFlags |= DDSD_PIXELFORMAT;
14338 desc.ddpfPixelFormat = current_format;
14339 hr = IDirectDraw2_EnumDisplayModes(ddraw, 0, &desc, &param, build_mode_list_cb);
14340 ok(hr == DD_OK, "Failed to build mode list, hr %#lx.\n", hr);
14342 param.count = 0;
14343 desc.dwFlags &= ~DDSD_PIXELFORMAT;
14344 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
14345 &desc, &param, enum_surfaces_create_cb);
14346 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
14347 ok(param.count == param.mode_count, "Expected %u surfaces, got %u.\n", param.mode_count, param.count);
14349 desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
14350 desc.dwWidth = desc.dwHeight = 32;
14352 param.modes[0].dwWidth = param.modes[0].dwHeight = 32;
14354 param.count = 0;
14355 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
14356 &desc, &param, enum_surfaces_create_cb);
14357 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
14358 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14360 hr = IDirectDraw2_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL);
14361 ok(hr == DD_OK, "Failed to create surface, hr %#lx.\n", hr);
14362 param.count = 0;
14363 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
14364 &desc, &param, enum_surfaces_create_cb);
14365 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
14366 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14367 IDirectDrawSurface2_Release(param.surfaces[0]);
14369 desc.dwFlags |= DDSD_PIXELFORMAT;
14370 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
14371 desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
14372 desc.ddpfPixelFormat.dwFourCC = 0xdeadbeef;
14374 param.count = 0;
14375 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
14376 &desc, &param, enum_surfaces_create_cb);
14377 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
14378 ok(!param.count, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14380 IDirectDraw2_Release(ddraw);
14383 static void test_viewport(void)
14385 static struct
14387 D3DVIEWPORT7 vp;
14388 RECT expected_rect;
14389 const char *message;
14391 tests[] =
14393 {{ 0, 0, 640, 480}, { 0, 120, 479, 359}, "Viewport (0, 0) - (640, 480)"},
14394 {{ 0, 0, 320, 240}, { 0, 60, 239, 179}, "Viewport (0, 0) - (320, 240)"},
14395 {{ 0, 0, 1280, 960}, { 0, 240, 639, 479}, "Viewport (0, 0) - (1280, 960)"},
14396 {{ 0, 0, 2000, 1600}, { 0, 400, 639, 479}, "Viewport (0, 0) - (2000, 1600)"},
14397 {{100, 100, 640, 480}, {100, 220, 579, 459}, "Viewport (100, 100) - (640, 480)"},
14398 {{ 0, 0, 8192, 8192}, {-10, -10, -10, -10}, "Viewport (0, 0) - (8192, 8192)"},
14400 static const struct
14402 unsigned int x, y;
14404 rt_sizes[] =
14406 {640, 480}, {1280, 960}, {320, 240}, {800, 600},
14408 static D3DMATRIX mat =
14410 1.0f, 0.0f, 0.0f, 0.0f,
14411 0.0f, 1.0f, 0.0f, 0.0f,
14412 0.0f, 0.0f, 1.0f, 0.0f,
14413 0.0f, 0.0f, 0.0f, 1.0f,
14415 static D3DLVERTEX quad[] =
14417 {{-1.5f}, {-0.5f}, {0.1f}, 0, {0xffffffff}},
14418 {{-1.5f}, { 0.5f}, {0.1f}, 0, {0xffffffff}},
14419 {{ 0.5f}, {-0.5f}, {0.1f}, 0, {0xffffffff}},
14420 {{ 0.5f}, { 0.5f}, {0.1f}, 0, {0xffffffff}},
14422 IDirect3DViewport2 *viewport, *full_viewport;
14423 IDirect3DMaterial2 *black_background;
14424 IDirectDrawSurface *rt, *ds;
14425 DDSURFACEDESC surface_desc;
14426 IDirect3DDevice2 *device;
14427 BOOL expected_failure;
14428 IDirectDraw2 *ddraw;
14429 DDPIXELFORMAT z_fmt;
14430 D3DRECT clear_rect;
14431 unsigned int i, j;
14432 IDirect3D2 *d3d;
14433 D3DVIEWPORT vp;
14434 ULONG refcount;
14435 HWND window;
14436 HRESULT hr;
14438 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
14439 0, 0, 640, 480, NULL, NULL, NULL, NULL);
14440 ddraw = create_ddraw();
14441 ok(!!ddraw, "Failed to create a ddraw object.\n");
14442 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
14444 skip("Failed to create a 3D device, skipping test.\n");
14445 IDirectDraw2_Release(ddraw);
14446 DestroyWindow(window);
14447 return;
14450 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
14451 ok(SUCCEEDED(hr), "Failed to get Direct3D2 interface, hr %#lx.\n", hr);
14453 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
14454 ok(SUCCEEDED(hr), "Failed to disable depth test, hr %#lx.\n", hr);
14455 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
14456 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#lx.\n", hr);
14458 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
14459 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
14460 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
14461 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#lx.\n", hr);
14462 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
14463 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#lx.\n", hr);
14465 black_background = create_diffuse_material(device, 0.0f, 0.0f, 0.0f, 0.0f);
14467 ds = get_depth_stencil(device);
14468 memset(&surface_desc, 0, sizeof(surface_desc));
14469 surface_desc.dwSize = sizeof(surface_desc);
14470 hr = IDirectDrawSurface_GetSurfaceDesc(ds, &surface_desc);
14471 z_fmt = surface_desc.ddpfPixelFormat;
14473 for (i = 0; i < ARRAY_SIZE(rt_sizes); ++i)
14475 winetest_push_context("Size %ux%u", rt_sizes[i].x, rt_sizes[i].y);
14477 if (i)
14479 memset(&surface_desc, 0, sizeof(surface_desc));
14480 surface_desc.dwSize = sizeof(surface_desc);
14481 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
14482 surface_desc.dwWidth = rt_sizes[i].x;
14483 surface_desc.dwHeight = rt_sizes[i].y;
14484 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
14485 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &rt, NULL);
14486 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14488 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
14489 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
14490 surface_desc.ddpfPixelFormat = z_fmt;
14491 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
14492 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14493 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
14494 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14496 hr = IDirect3DDevice2_SetRenderTarget(device, rt, 0);
14497 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14499 else
14501 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
14502 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14505 full_viewport = create_viewport(device, 0, 0, rt_sizes[i].x, rt_sizes[i].y);
14506 viewport_set_background(device, full_viewport, black_background);
14508 clear_rect.x1 = clear_rect.y1 = 0;
14509 clear_rect.x2 = rt_sizes[i].x;
14510 clear_rect.y2 = rt_sizes[i].y;
14512 for (j = 0; j < ARRAY_SIZE(tests); ++j)
14514 winetest_push_context("%s", tests[j].message);
14516 expected_failure = tests[j].vp.dwX + tests[j].vp.dwWidth > rt_sizes[i].x
14517 || tests[j].vp.dwY + tests[j].vp.dwHeight > rt_sizes[i].y;
14519 hr = IDirect3DViewport2_Clear(full_viewport, 1, &clear_rect, D3DCLEAR_TARGET);
14520 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14522 hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
14523 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14524 hr = IDirect3DViewport2_SetViewport2(viewport, NULL);
14525 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
14526 memset(&vp, 0, sizeof(vp));
14527 vp.dwSize = sizeof(vp);
14528 vp.dwX = tests[j].vp.dwX;
14529 vp.dwY = tests[j].vp.dwY;
14530 vp.dwWidth = tests[j].vp.dwWidth;
14531 vp.dwHeight = tests[j].vp.dwHeight;
14532 vp.dvScaleX = tests[j].vp.dwWidth / 2.0f;
14533 vp.dvScaleY = tests[j].vp.dwHeight / 2.0f;
14534 vp.dvMinZ = 0.0f;
14535 vp.dvMaxZ = 1.0f;
14536 hr = IDirect3DViewport2_SetViewport(viewport, &vp);
14537 ok(hr == D3DERR_VIEWPORTHASNODEVICE, "Got unexpected hr %#lx.\n", hr);
14538 hr = IDirect3DDevice2_AddViewport(device, viewport);
14539 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14540 hr = IDirect3DViewport2_SetViewport(viewport, &vp);
14541 ok(hr == (expected_failure ? E_INVALIDARG : DD_OK), "Got unexpected hr %#lx.\n", hr);
14543 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
14544 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14545 if (expected_failure)
14547 destroy_viewport(device, viewport);
14548 winetest_pop_context();
14549 continue;
14552 hr = IDirect3DDevice2_BeginScene(device);
14553 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14554 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
14555 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14556 hr = IDirect3DDevice2_EndScene(device);
14557 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14559 check_rect(rt, tests[j].expected_rect);
14561 destroy_viewport(device, viewport);
14562 winetest_pop_context();
14565 destroy_viewport(device, full_viewport);
14567 hr = IDirectDrawSurface_DeleteAttachedSurface(rt, 0, ds);
14568 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx (i %u).\n", hr, i);
14569 IDirectDrawSurface_Release(ds);
14571 IDirectDrawSurface_Release(rt);
14573 winetest_pop_context();
14576 destroy_material(black_background);
14577 refcount = IDirect3DDevice2_Release(device);
14578 ok(!refcount, "Device has %lu references left.\n", refcount);
14579 IDirect3D2_Release(d3d);
14580 IDirectDraw2_Release(ddraw);
14581 DestroyWindow(window);
14584 static void test_find_device(void)
14586 D3DFINDDEVICESEARCH search = {0};
14587 D3DFINDDEVICERESULT result = {0};
14588 IDirect3DDevice2 *device;
14589 IDirectDraw2 *ddraw;
14590 IDirect3D2 *d3d;
14591 unsigned int i;
14592 HWND window;
14593 HRESULT hr;
14595 struct
14597 DWORD size;
14598 GUID guid;
14599 D3DDEVICEDESC_V1 hw_desc;
14600 D3DDEVICEDESC_V1 sw_desc;
14601 } result_v1;
14603 struct
14605 DWORD size;
14606 GUID guid;
14607 D3DDEVICEDESC_V2 hw_desc;
14608 D3DDEVICEDESC_V2 sw_desc;
14609 } result_v2;
14611 static const struct
14613 const GUID *guid;
14614 HRESULT hr;
14616 tests[] =
14618 {&IID_IDirect3D, DDERR_NOTFOUND},
14619 {&IID_IDirect3DRampDevice, D3D_OK},
14620 {&IID_IDirect3DRGBDevice, D3D_OK},
14621 {&IID_IDirect3DMMXDevice, D3D_OK},
14622 {&IID_IDirect3DRefDevice, DDERR_NOTFOUND},
14623 {&IID_IDirect3DTnLHalDevice, DDERR_NOTFOUND},
14624 {&IID_IDirect3DNullDevice, DDERR_NOTFOUND},
14627 ddraw = create_ddraw();
14628 ok(!!ddraw, "Failed to create a ddraw object.\n");
14630 if (FAILED(IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
14632 skip("D3D interface is not available, skipping test.\n");
14633 IDirectDraw2_Release(ddraw);
14634 return;
14637 result.dwSize = sizeof(result);
14638 search.dwSize = sizeof(search);
14639 hr = IDirect3D2_FindDevice(d3d, NULL, NULL);
14640 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
14641 hr = IDirect3D2_FindDevice(d3d, NULL, &result);
14642 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
14643 hr = IDirect3D2_FindDevice(d3d, &search, NULL);
14644 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
14645 hr = IDirect3D2_FindDevice(d3d, &search, &result);
14646 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14647 ok(result.dwSize == sizeof(result), "Got unexpected result size %lu.\n", result.dwSize);
14648 ok(result.ddHwDesc.dwSize == sizeof(result_v2.hw_desc),
14649 "Got unexpected HW desc size %lu.\n", result.ddHwDesc.dwSize);
14650 ok(result.ddSwDesc.dwSize == sizeof(result_v2.sw_desc),
14651 "Got unexpected SW desc size %lu.\n", result.ddSwDesc.dwSize);
14653 memset(&search, 0, sizeof(search));
14654 memset(&result, 0, sizeof(result));
14655 hr = IDirect3D2_FindDevice(d3d, &search, &result);
14656 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
14658 search.dwSize = sizeof(search) + 1;
14659 result.dwSize = sizeof(result) + 1;
14660 hr = IDirect3D2_FindDevice(d3d, &search, &result);
14661 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
14663 search.dwSize = sizeof(search);
14665 memset(&result_v1, 0, sizeof(result_v1));
14666 result_v1.size = sizeof(result_v1);
14667 hr = IDirect3D2_FindDevice(d3d, &search, (D3DFINDDEVICERESULT *)&result_v1);
14668 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14669 ok(result_v1.hw_desc.dwSize == sizeof(result_v2.hw_desc),
14670 "Got unexpected HW desc size %lu.\n", result_v1.hw_desc.dwSize);
14671 ok(result_v1.sw_desc.dwSize == sizeof(result_v2.sw_desc),
14672 "Got unexpected SW desc size %lu.\n", result_v1.sw_desc.dwSize);
14674 memset(&result_v2, 0, sizeof(result_v2));
14675 result_v2.size = sizeof(result_v2);
14676 hr = IDirect3D2_FindDevice(d3d, &search, (D3DFINDDEVICERESULT *)&result_v2);
14677 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14678 ok(result_v2.hw_desc.dwSize == sizeof(result_v2.hw_desc),
14679 "Got unexpected HW desc size %lu.\n", result_v2.hw_desc.dwSize);
14680 ok(result_v2.sw_desc.dwSize == sizeof(result_v2.sw_desc),
14681 "Got unexpected SW desc size %lu.\n", result_v2.sw_desc.dwSize);
14683 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14685 memset(&search, 0, sizeof(search));
14686 search.dwSize = sizeof(search);
14687 search.dwFlags = D3DFDS_GUID;
14688 search.guid = *tests[i].guid;
14690 memset(&result, 0, sizeof(result));
14691 result.dwSize = sizeof(result);
14693 hr = IDirect3D2_FindDevice(d3d, &search, &result);
14694 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#lx.\n", i, hr);
14695 ok(result.dwSize == sizeof(result), "Test %u: Got unexpected result size %lu.\n", i, result.dwSize);
14696 if (SUCCEEDED(hr))
14698 ok(result.ddHwDesc.dwSize == sizeof(result_v2.hw_desc),
14699 "Test %u: Got unexpected HW desc size %lu.\n", i, result.ddHwDesc.dwSize);
14700 ok(result.ddSwDesc.dwSize == sizeof(result_v2.sw_desc),
14701 "Test %u: Got unexpected SW desc size %lu.\n", i, result.ddSwDesc.dwSize);
14703 else
14705 ok(!result.ddHwDesc.dwSize,
14706 "Test %u: Got unexpected HW desc size %lu.\n", i, result.ddHwDesc.dwSize);
14707 ok(!result.ddSwDesc.dwSize,
14708 "Test %u: Got unexpected SW desc size %lu.\n", i, result.ddSwDesc.dwSize);
14712 /* The HAL device can only be enumerated if hardware acceleration is present. */
14713 search.dwSize = sizeof(search);
14714 search.dwFlags = D3DFDS_GUID;
14715 search.guid = IID_IDirect3DHALDevice;
14716 result.dwSize = sizeof(result);
14717 hr = IDirect3D2_FindDevice(d3d, &search, &result);
14719 window = create_window();
14720 device = create_device(ddraw, window, DDSCL_NORMAL);
14721 if (hr == D3D_OK)
14722 ok(!!device, "Failed to create a 3D device.\n");
14723 else
14724 ok(!device, "Succeeded to create a 3D device.\n");
14725 if (device)
14726 IDirect3DDevice2_Release(device);
14727 DestroyWindow(window);
14729 /* Curiously the colour model criteria seem to be ignored. */
14730 search.dwSize = sizeof(search);
14731 search.dwFlags = D3DFDS_COLORMODEL;
14732 search.dcmColorModel = 0xdeadbeef;
14733 result.dwSize = sizeof(result);
14734 hr = IDirect3D2_FindDevice(d3d, &search, &result);
14735 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14737 IDirect3D2_Release(d3d);
14738 IDirectDraw2_Release(ddraw);
14741 static IDirectDraw2 *killfocus_ddraw;
14742 static IDirectDrawSurface *killfocus_surface;
14744 static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
14746 ULONG ref;
14748 if (message == WM_KILLFOCUS)
14750 ref = IDirectDrawSurface_Release(killfocus_surface);
14751 ok(!ref, "Unexpected surface refcount %lu.\n", ref);
14752 ref = IDirectDraw2_Release(killfocus_ddraw);
14753 ok(!ref, "Unexpected ddraw refcount %lu.\n", ref);
14754 killfocus_ddraw = NULL;
14757 return DefWindowProcA(window, message, wparam, lparam);
14760 static void test_killfocus(void)
14762 DDSURFACEDESC surface_desc;
14763 HRESULT hr;
14764 HWND window;
14765 WNDCLASSA wc = {0};
14767 wc.lpfnWndProc = killfocus_proc;
14768 wc.lpszClassName = "ddraw_killfocus_wndproc_wc";
14769 ok(RegisterClassA(&wc), "Failed to register window class.\n");
14771 window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
14772 0, 0, 640, 480, 0, 0, 0, 0);
14774 killfocus_ddraw = create_ddraw();
14775 ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n");
14777 hr = IDirectDraw2_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
14778 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
14780 memset(&surface_desc, 0, sizeof(surface_desc));
14781 surface_desc.dwSize = sizeof(surface_desc);
14782 surface_desc.dwFlags = DDSD_CAPS;
14783 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
14784 hr = IDirectDraw2_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL);
14785 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
14787 SetForegroundWindow(GetDesktopWindow());
14788 ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n");
14790 DestroyWindow(window);
14791 UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
14794 static void test_gdi_surface(void)
14796 IDirectDrawSurface *primary, *backbuffer, *gdi_surface;
14797 DDSCAPS caps = {DDSCAPS_BACKBUFFER};
14798 DDSURFACEDESC surface_desc;
14799 IDirectDraw2 *ddraw;
14800 ULONG refcount;
14801 HWND window;
14802 HRESULT hr;
14804 window = create_window();
14805 ddraw = create_ddraw();
14806 ok(!!ddraw, "Failed to create a ddraw object.\n");
14807 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
14808 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14810 /* Retrieving the GDI surface requires a primary surface to exist. */
14811 gdi_surface = (void *)0xc0dec0de;
14812 hr = IDirectDraw2_GetGDISurface(ddraw, &gdi_surface);
14813 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
14814 ok(!gdi_surface, "Got unexpected surface %p.\n", gdi_surface);
14816 hr = IDirectDraw2_FlipToGDISurface(ddraw);
14817 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
14819 memset(&surface_desc, 0, sizeof(surface_desc));
14820 surface_desc.dwSize = sizeof(surface_desc);
14821 surface_desc.dwFlags = DDSD_CAPS;
14822 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
14823 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
14824 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14826 hr = IDirectDraw2_GetGDISurface(ddraw, &gdi_surface);
14827 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14828 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
14829 IDirectDrawSurface_Release(gdi_surface);
14831 /* Flipping to the GDI surface requires the primary surface to be
14832 * flippable. */
14833 hr = IDirectDraw2_FlipToGDISurface(ddraw);
14834 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#lx.\n", hr);
14836 IDirectDrawSurface_Release(primary);
14838 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
14839 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14841 memset(&surface_desc, 0, sizeof(surface_desc));
14842 surface_desc.dwSize = sizeof(surface_desc);
14843 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
14844 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
14845 surface_desc.dwBackBufferCount = 1;
14846 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
14847 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14848 hr = IDirectDrawSurface_GetAttachedSurface(primary, &caps, &backbuffer);
14849 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14850 ok(backbuffer != primary, "Got unexpected backbuffer %p.\n", backbuffer);
14852 hr = IDirectDraw2_GetGDISurface(ddraw, &gdi_surface);
14853 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14854 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
14855 IDirectDrawSurface_Release(gdi_surface);
14857 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
14858 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14859 hr = IDirectDraw2_GetGDISurface(ddraw, &gdi_surface);
14860 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14861 ok(gdi_surface == backbuffer || broken(gdi_surface == primary),
14862 "Got unexpected surface %p, expected %p.\n", gdi_surface, backbuffer);
14863 IDirectDrawSurface_Release(gdi_surface);
14865 hr = IDirectDraw2_FlipToGDISurface(ddraw);
14866 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14868 hr = IDirectDraw2_GetGDISurface(ddraw, &gdi_surface);
14869 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14870 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
14871 IDirectDrawSurface_Release(gdi_surface);
14873 hr = IDirectDraw2_FlipToGDISurface(ddraw);
14874 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
14876 IDirectDrawSurface_Release(backbuffer);
14877 IDirectDrawSurface_Release(primary);
14879 refcount = IDirectDraw2_Release(ddraw);
14880 ok(!refcount, "%lu references left.\n", refcount);
14881 DestroyWindow(window);
14884 static void test_alphatest(void)
14886 #define ALPHATEST_PASSED 0x0000ff00
14887 #define ALPHATEST_FAILED 0x00ff0000
14888 D3DRECT rect_full = {{0}, {0}, {640}, {480}};
14889 IDirect3DMaterial2 *blue, *failed;
14890 IDirect3DViewport2 *viewport;
14891 IDirect3DDevice2 *device;
14892 IDirectDrawSurface *rt;
14893 unsigned int color, i;
14894 IDirectDraw2 *ddraw;
14895 ULONG refcount;
14896 HWND window;
14897 DWORD value;
14898 HRESULT hr;
14900 static const struct
14902 D3DCMPFUNC func;
14903 unsigned int color_less, color_equal, color_greater;
14905 test_data[] =
14907 {D3DCMP_NEVER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED},
14908 {D3DCMP_LESS, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED},
14909 {D3DCMP_EQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED},
14910 {D3DCMP_LESSEQUAL, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_FAILED},
14911 {D3DCMP_GREATER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_PASSED},
14912 {D3DCMP_NOTEQUAL, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED},
14913 {D3DCMP_GREATEREQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED},
14914 {D3DCMP_ALWAYS, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
14916 static D3DLVERTEX quad[] =
14918 {{-1.0f}, {-1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
14919 {{-1.0f}, { 1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
14920 {{ 1.0f}, {-1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
14921 {{ 1.0f}, { 1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
14924 window = create_window();
14925 ddraw = create_ddraw();
14926 ok(!!ddraw, "Failed to create a ddraw object.\n");
14927 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
14929 skip("Failed to create a 3D device.\n");
14930 IDirectDraw2_Release(ddraw);
14931 DestroyWindow(window);
14932 return;
14934 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
14935 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14937 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
14938 failed = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
14940 viewport = create_viewport(device, 0, 0, 640, 480);
14941 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
14942 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14944 viewport_set_background(device, viewport, blue);
14945 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
14946 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14947 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
14948 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14949 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
14950 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14951 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
14952 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14954 viewport_set_background(device, viewport, failed);
14955 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
14957 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHAFUNC, test_data[i].func);
14958 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14960 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
14961 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14962 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0x70);
14963 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14964 hr = IDirect3DDevice2_BeginScene(device);
14965 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14966 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
14967 D3DVT_LVERTEX, quad, ARRAY_SIZE(quad), 0);
14968 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14969 hr = IDirect3DDevice2_EndScene(device);
14970 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14971 color = get_surface_color(rt, 320, 240);
14972 ok(compare_color(color, test_data[i].color_greater, 0),
14973 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
14974 color, test_data[i].color_greater, test_data[i].func);
14976 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
14977 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14978 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0xff70);
14979 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14980 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHAREF, &value);
14981 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14982 ok(value == 0xff70, "Got unexpected value %#lx.\n", value);
14983 hr = IDirect3DDevice2_BeginScene(device);
14984 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14985 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
14986 D3DVT_LVERTEX, quad, ARRAY_SIZE(quad), 0);
14987 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14988 hr = IDirect3DDevice2_EndScene(device);
14989 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
14990 color = get_surface_color(rt, 320, 240);
14991 ok(compare_color(color, test_data[i].color_greater, 0),
14992 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
14993 color, test_data[i].color_greater, test_data[i].func);
14996 destroy_viewport(device, viewport);
14997 destroy_material(failed);
14998 destroy_material(blue);
14999 IDirectDrawSurface_Release(rt);
15000 refcount = IDirect3DDevice2_Release(device);
15001 ok(!refcount, "Device has %lu references left.\n", refcount);
15002 refcount = IDirectDraw2_Release(ddraw);
15003 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
15004 DestroyWindow(window);
15007 static void test_clipper_refcount(void)
15009 IDirectDrawSurface *surface;
15010 IDirectDrawClipper *clipper, *clipper2;
15011 DDSURFACEDESC surface_desc;
15012 IDirectDraw2 *ddraw;
15013 IDirectDraw *ddraw1;
15014 ULONG refcount;
15015 HWND window;
15016 HRESULT hr;
15017 BOOL changed;
15018 const IDirectDrawClipperVtbl *orig_vtbl;
15020 window = create_window();
15021 ddraw = create_ddraw();
15022 ok(!!ddraw, "Failed to create a ddraw object.\n");
15023 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
15024 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
15026 memset(&surface_desc, 0, sizeof(surface_desc));
15027 surface_desc.dwSize = sizeof(surface_desc);
15028 surface_desc.dwFlags = DDSD_CAPS;
15029 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
15030 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
15031 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
15033 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
15034 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
15035 refcount = get_refcount((IUnknown *)clipper);
15036 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
15038 /* Show that clipper validation doesn't somehow happen through per-clipper vtable
15039 * pointers. */
15040 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper2, NULL);
15041 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
15042 ok(clipper->lpVtbl == clipper2->lpVtbl, "Got different clipper vtables %p and %p.\n",
15043 clipper->lpVtbl, clipper2->lpVtbl);
15044 orig_vtbl = clipper->lpVtbl;
15045 IDirectDrawClipper_Release(clipper2);
15047 /* Surfaces hold a reference to clippers. No surprises there. */
15048 hr = IDirectDrawSurface_SetClipper(surface, clipper);
15049 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
15050 refcount = get_refcount((IUnknown *)clipper);
15051 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
15053 hr = IDirectDrawSurface_GetClipper(surface, &clipper2);
15054 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#lx.\n", hr);
15055 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
15056 refcount = IDirectDrawClipper_Release(clipper2);
15057 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
15059 hr = IDirectDrawSurface_SetClipper(surface, NULL);
15060 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
15061 refcount = get_refcount((IUnknown *)clipper);
15062 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
15064 hr = IDirectDrawSurface_SetClipper(surface, clipper);
15065 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
15066 refcount = get_refcount((IUnknown *)clipper);
15067 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
15069 refcount = IDirectDrawSurface_Release(surface);
15070 ok(!refcount, "%lu references left.\n", refcount);
15071 refcount = get_refcount((IUnknown *)clipper);
15072 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
15074 /* SetClipper with an invalid pointer crashes. */
15076 /* Clipper methods work with a broken vtable, with the exception of Release. */
15077 clipper->lpVtbl = (void *)0xdeadbeef;
15078 refcount = orig_vtbl->AddRef(clipper);
15079 todo_wine ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
15080 refcount = orig_vtbl->Release(clipper);
15081 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
15083 clipper->lpVtbl = orig_vtbl;
15084 refcount = orig_vtbl->Release(clipper);
15085 todo_wine ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
15087 /* Fix the refcount difference because Wine did not increase the ref in the
15088 * AddRef call above. */
15089 if (refcount)
15091 refcount = IDirectDrawClipper_Release(clipper);
15092 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
15095 /* Steal the reference and see what happens - releasing the surface works fine.
15096 * The clipper is destroyed and not kept alive by a hidden refcount - trying to
15097 * release it after the GetClipper call is likely to crash, and certain to crash
15098 * if we allocate and zero as much heap memory as we can get. */
15099 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
15100 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
15101 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
15102 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
15103 hr = IDirectDrawSurface_SetClipper(surface, clipper);
15104 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
15106 IDirectDrawClipper_Release(clipper);
15107 IDirectDrawClipper_Release(clipper);
15109 if (0)
15111 /* Disabled because it causes heap corruption (HeapValidate fails and random
15112 * hangs in a later HeapFree) on Windows on one of my Machines: MacbookPro 10,1
15113 * running Windows 10 18363.535 and Nvidia driver 425.31. Driver version 441.66
15114 * is affected too. Some testbot machines have crashes directly in GetClipper
15115 * or proceed with a corrupted heap too.
15117 * The same Windows and driver versions run the test without heap corruption on
15118 * a Geforce 1060 GTX card. I have not seen the problem on AMD GPUs either. */
15119 hr = IDirectDrawSurface_GetClipper(surface, &clipper2);
15120 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#lx.\n", hr);
15121 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
15124 /* Show that invoking the Release method does not crash, but don't get the
15125 * vtable through the clipper pointer because it is no longer pointing to
15126 * valid memory. */
15127 refcount = orig_vtbl->Release(clipper);
15128 ok(!refcount, "%lu references left.\n", refcount);
15130 refcount = IDirectDrawSurface_Release(surface);
15131 ok(!refcount, "%lu references left.\n", refcount);
15133 /* It looks like the protection against invalid thispointers is part of
15134 * the IDirectDrawClipper method implementation, not IDirectDrawSurface. */
15135 clipper = calloc(1, 0x1000);
15136 ok(!!clipper, "failed to allocate memory\n");
15138 /* Assigning the vtable to our fake clipper does NOT make a difference on
15139 * native - there is a different member of the clipper implementation struct
15140 * that is used to determine if a clipper is valid. */
15141 clipper->lpVtbl = orig_vtbl;
15143 refcount = orig_vtbl->AddRef(clipper);
15144 todo_wine ok(!refcount, "Got refcount %lu.\n", refcount);
15145 refcount = orig_vtbl->AddRef((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef);
15146 ok(!refcount, "Got refcount %lu.\n", refcount);
15148 changed = 0x1234;
15149 hr = orig_vtbl->IsClipListChanged(clipper, &changed);
15150 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
15151 todo_wine ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
15153 changed = 0x1234;
15154 hr = orig_vtbl->IsClipListChanged((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef, &changed);
15155 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
15156 ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
15158 /* Nope, we can't initialize our fake clipper. */
15159 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirectDraw, (void **)&ddraw1);
15160 ok(SUCCEEDED(hr), "Failed to get ddraw1 interface, hr %#lx.\n", hr);
15162 hr = orig_vtbl->Initialize(clipper, ddraw1, 0);
15163 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
15165 IDirectDraw_Release(ddraw1);
15167 free(clipper);
15169 refcount = IDirectDraw2_Release(ddraw);
15170 ok(!refcount, "%lu references left.\n", refcount);
15171 DestroyWindow(window);
15174 static void test_caps(void)
15176 DWORD caps_never, caps_always, caps_hal;
15177 DDCAPS hal_caps, hel_caps;
15178 IDirectDraw2 *ddraw;
15179 IDirectDraw *ddraw1;
15180 HRESULT hr;
15181 BOOL no3d;
15183 caps_never = DDSCAPS_RESERVED1
15184 | DDSCAPS_ALPHA
15185 | DDSCAPS_PRIMARYSURFACELEFT
15186 | DDSCAPS_SYSTEMMEMORY
15187 | DDSCAPS_VISIBLE
15188 | DDSCAPS_WRITEONLY
15189 | DDSCAPS_LIVEVIDEO
15190 | DDSCAPS_HWCODEC
15191 | DDSCAPS_MODEX
15192 | DDSCAPS_RESERVED2
15193 | 0x01000000u
15194 | 0x02000000u
15195 | DDSCAPS_ALLOCONLOAD
15196 | DDSCAPS_VIDEOPORT
15197 | DDSCAPS_STANDARDVGAMODE
15198 | DDSCAPS_OPTIMIZED;
15200 caps_always = DDSCAPS_FLIP
15201 | DDSCAPS_OFFSCREENPLAIN
15202 | DDSCAPS_PRIMARYSURFACE
15203 | DDSCAPS_TEXTURE
15204 | DDSCAPS_ZBUFFER
15205 | DDSCAPS_MIPMAP;
15207 caps_hal = DDSCAPS_BACKBUFFER
15208 | DDSCAPS_COMPLEX
15209 | DDSCAPS_FRONTBUFFER
15210 | DDSCAPS_3DDEVICE
15211 | DDSCAPS_VIDEOMEMORY
15212 | DDSCAPS_LOCALVIDMEM
15213 | DDSCAPS_NONLOCALVIDMEM;
15215 ddraw = create_ddraw();
15216 ok(!!ddraw, "Failed to create a ddraw object.\n");
15218 memset(&hal_caps, 0, sizeof(hal_caps));
15219 memset(&hel_caps, 0, sizeof(hel_caps));
15220 hal_caps.dwSize = sizeof(hal_caps);
15221 hel_caps.dwSize = sizeof(hel_caps);
15222 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, &hel_caps);
15223 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
15224 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
15225 "Got unexpected caps %#lx, expected %#lx.\n",
15226 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
15227 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
15228 "Got unexpected caps %#lx, expected %#lx.\n",
15229 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
15231 no3d = !(hal_caps.ddsCaps.dwCaps & DDSCAPS_3DDEVICE);
15232 if (hal_caps.ddsCaps.dwCaps)
15234 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
15235 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
15236 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
15237 "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
15239 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
15240 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
15241 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
15242 "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
15244 IDirectDraw2_Release(ddraw);
15246 if (hal_caps.ddsCaps.dwCaps)
15248 hr = DirectDrawCreate((GUID *)DDCREATE_HARDWAREONLY, &ddraw1, NULL);
15249 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
15250 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw);
15251 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
15252 IDirectDraw_Release(ddraw1);
15254 memset(&hal_caps, 0, sizeof(hal_caps));
15255 memset(&hel_caps, 0, sizeof(hel_caps));
15256 hal_caps.dwSize = sizeof(hal_caps);
15257 hel_caps.dwSize = sizeof(hel_caps);
15258 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, &hel_caps);
15259 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
15260 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
15261 "Got unexpected caps %#lx, expected %#lx.\n",
15262 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
15263 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
15264 "Got unexpected caps %#lx, expected %#lx.\n",
15265 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
15267 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
15268 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
15269 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
15270 "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
15271 if (is_ddraw64)
15273 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
15274 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
15275 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
15276 "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
15278 else
15280 todo_wine ok(!hel_caps.ddsCaps.dwCaps, "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
15283 IDirectDraw2_Release(ddraw);
15286 hr = DirectDrawCreate((GUID *)DDCREATE_EMULATIONONLY, &ddraw1, NULL);
15287 ok(hr == DD_OK || (is_ddraw64 && hr == E_FAIL), "Got unexpected hr %#lx.\n", hr);
15288 if (SUCCEEDED(hr))
15290 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw);
15291 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
15292 IDirectDraw_Release(ddraw1);
15294 memset(&hal_caps, 0, sizeof(hal_caps));
15295 memset(&hel_caps, 0, sizeof(hel_caps));
15296 hal_caps.dwSize = sizeof(hal_caps);
15297 hel_caps.dwSize = sizeof(hel_caps);
15298 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, &hel_caps);
15299 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
15300 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
15301 "Got unexpected caps %#lx, expected %#lx.\n",
15302 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
15303 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
15304 "Got unexpected caps %#lx, expected %#lx.\n",
15305 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
15307 todo_wine ok(!hal_caps.ddsCaps.dwCaps, "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
15308 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
15309 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
15310 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
15311 "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
15313 IDirectDraw2_Release(ddraw);
15317 static void test_d32_support(void)
15319 IDirectDrawSurface *surface;
15320 DDSURFACEDESC surface_desc;
15321 IDirectDraw2 *ddraw;
15322 ULONG refcount;
15323 HWND window;
15324 HRESULT hr;
15326 window = create_window();
15327 ddraw = create_ddraw();
15328 ok(!!ddraw, "Failed to create a ddraw object.\n");
15329 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
15330 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
15332 memset(&surface_desc, 0, sizeof(surface_desc));
15333 surface_desc.dwSize = sizeof(surface_desc);
15334 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
15335 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
15336 surface_desc.dwZBufferBitDepth = 32;
15337 surface_desc.dwWidth = 64;
15338 surface_desc.dwHeight = 64;
15339 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
15340 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
15342 memset(&surface_desc, 0, sizeof(surface_desc));
15343 surface_desc.dwSize = sizeof(surface_desc);
15344 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
15345 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
15346 ok((surface_desc.dwFlags & DDSD_ZBUFFERBITDEPTH), "Got unexpected flags %#lx.\n", surface_desc.dwFlags);
15347 ok(surface_desc.dwZBufferBitDepth == 32,
15348 "Got unexpected dwZBufferBitDepth %lu.\n", surface_desc.dwZBufferBitDepth);
15349 ok(!(surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY),
15350 "Got unexpected surface caps %#lx.\n", surface_desc.ddsCaps.dwCaps);
15351 IDirectDrawSurface_Release(surface);
15353 refcount = IDirectDraw2_Release(ddraw);
15354 ok(!refcount, "%lu references left.\n", refcount);
15355 DestroyWindow(window);
15358 struct find_different_mode_param
15360 unsigned int old_width;
15361 unsigned int old_height;
15362 unsigned int old_frequency;
15363 unsigned int new_width;
15364 unsigned int new_height;
15365 unsigned int new_frequency;
15366 unsigned int new_bpp;
15369 static HRESULT CALLBACK find_different_mode_callback(DDSURFACEDESC *surface_desc, void *context)
15371 struct find_different_mode_param *param = context;
15373 if (surface_desc->ddpfPixelFormat.dwRGBBitCount != registry_mode.dmBitsPerPel)
15374 return DDENUMRET_OK;
15376 /* See comment in ddraw7 about the frequency. */
15377 if (surface_desc->dwWidth != param->old_width && surface_desc->dwHeight != param->old_height &&
15378 (!compare_uint(surface_desc->dwRefreshRate, param->old_frequency, 1) || !param->old_frequency))
15380 /* See test_coop_level_mode_set_enum_cb() for why enumeration might accidentally continue. */
15381 if (!param->new_width || (param->new_width < registry_mode.dmPelsWidth
15382 && param->new_height < registry_mode.dmPelsHeight))
15384 param->new_width = surface_desc->dwWidth;
15385 param->new_height = surface_desc->dwHeight;
15386 param->new_frequency = surface_desc->dwRefreshRate;
15387 param->new_bpp = surface_desc->ddpfPixelFormat.dwRGBBitCount;
15389 return DDENUMRET_CANCEL;
15392 return DDENUMRET_OK;
15395 static void test_cursor_clipping(void)
15397 struct find_different_mode_param param;
15398 DDSURFACEDESC surface_desc;
15399 RECT rect, clip_rect;
15400 IDirectDraw2 *ddraw;
15401 HWND window;
15402 HRESULT hr;
15403 BOOL ret;
15405 window = create_window();
15406 ok(!!window, "Failed to create a window.\n");
15407 ddraw = create_ddraw();
15408 ok(!!ddraw, "Failed to create a ddraw object.\n");
15410 memset(&surface_desc, 0, sizeof(surface_desc));
15411 surface_desc.dwSize = sizeof(surface_desc);
15412 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
15413 ok(hr == DD_OK, "GetDisplayMode failed, hr %#lx.\n", hr);
15415 memset(&param, 0, sizeof(param));
15416 param.old_width = surface_desc.dwWidth;
15417 param.old_height = surface_desc.dwHeight;
15418 hr = IDirectDraw2_EnumDisplayModes(ddraw, 0, NULL, &param, find_different_mode_callback);
15419 ok(hr == DD_OK, "EnumDisplayModes failed, hr %#lx.\n", hr);
15420 if (!(param.new_width && param.new_height))
15422 skip("Failed to find a different mode than %ux%u.\n", param.old_width, param.old_height);
15423 goto done;
15426 ret = ClipCursor(NULL);
15427 ok(ret, "ClipCursor failed, error %lu.\n", GetLastError());
15428 get_virtual_rect(&rect);
15429 ret = GetClipCursor(&clip_rect);
15430 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
15431 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15432 wine_dbgstr_rect(&clip_rect));
15434 /* Set cooperative level to normal */
15435 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
15436 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
15437 flush_events();
15438 get_virtual_rect(&rect);
15439 ret = GetClipCursor(&clip_rect);
15440 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
15441 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15442 wine_dbgstr_rect(&clip_rect));
15444 hr = set_display_mode(ddraw, param.new_width, param.new_height);
15445 ok(hr == DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode failed, hr %#lx.\n", hr);
15446 if (FAILED(hr))
15448 win_skip("SetDisplayMode failed, hr %#lx.\n", hr);
15449 goto done;
15451 flush_events();
15452 get_virtual_rect(&rect);
15453 ret = GetClipCursor(&clip_rect);
15454 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
15455 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15456 wine_dbgstr_rect(&clip_rect));
15458 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
15459 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#lx.\n", hr);
15460 flush_events();
15461 get_virtual_rect(&rect);
15462 ret = GetClipCursor(&clip_rect);
15463 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
15464 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15465 wine_dbgstr_rect(&clip_rect));
15467 /* Switch to full screen cooperative level */
15468 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
15469 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
15470 flush_events();
15471 SetRect(&rect, 0, 0, param.old_width, param.old_height);
15472 ret = GetClipCursor(&clip_rect);
15473 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
15474 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15475 wine_dbgstr_rect(&clip_rect));
15477 hr = set_display_mode(ddraw, param.new_width, param.new_height);
15478 ok(hr == DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode failed, hr %#lx.\n", hr);
15479 if (FAILED(hr))
15481 win_skip("SetDisplayMode failed, hr %#lx.\n", hr);
15482 goto done;
15484 flush_events();
15485 SetRect(&rect, 0, 0, param.new_width, param.new_height);
15486 ret = GetClipCursor(&clip_rect);
15487 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
15488 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15489 wine_dbgstr_rect(&clip_rect));
15491 /* Restore display mode */
15492 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
15493 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#lx.\n", hr);
15494 flush_events();
15495 SetRect(&rect, 0, 0, param.old_width, param.old_height);
15496 ret = GetClipCursor(&clip_rect);
15497 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
15498 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15499 wine_dbgstr_rect(&clip_rect));
15501 /* Switch to normal cooperative level */
15502 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
15503 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
15504 flush_events();
15505 get_virtual_rect(&rect);
15506 ret = GetClipCursor(&clip_rect);
15507 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
15508 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15509 wine_dbgstr_rect(&clip_rect));
15511 done:
15512 IDirectDraw2_Release(ddraw);
15513 DestroyWindow(window);
15516 static BOOL CALLBACK test_window_position_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect,
15517 LPARAM lparam)
15519 RECT primary_rect, window_rect, new_rect;
15520 IDirectDraw2 *ddraw;
15521 HWND window;
15522 HRESULT hr;
15523 BOOL ret;
15525 ddraw = create_ddraw();
15526 ok(!!ddraw, "Failed to create a ddraw object.\n");
15527 window = CreateWindowA("static", "ddraw_test", WS_POPUP | WS_VISIBLE, monitor_rect->left,
15528 monitor_rect->top, 100, 100, NULL, NULL, NULL, NULL);
15529 ok(!!window, "Failed to create a window.\n");
15530 flush_events();
15532 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
15533 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
15534 flush_events();
15535 ret = GetWindowRect(window, &window_rect);
15536 ok(ret, "GetWindowRect failed, error %lu.\n", GetLastError());
15537 SetRect(&primary_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
15538 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
15539 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
15541 new_rect = window_rect;
15542 --new_rect.right;
15543 --new_rect.bottom;
15545 ret = MoveWindow(window, new_rect.left, new_rect.top, new_rect.right - new_rect.left,
15546 new_rect.bottom - new_rect.top, TRUE);
15547 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
15548 ret = GetWindowRect(window, &window_rect);
15549 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
15550 ok(EqualRect(&window_rect, &new_rect),
15551 "Expected window rect %s, got %s.\n",
15552 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
15553 /* After processing window events window rectangle gets restored. But only once, the size set
15554 * on the second resize remains. */
15555 flush_events();
15556 ret = GetWindowRect(window, &window_rect);
15557 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
15558 /* Both Windows and Wine change the size of the window. On Windows it is exactly the new size but in Wine
15559 * it may get adjusted depending on window manager. */
15560 ok(window_rect.right != monitor_rect->right && window_rect.bottom != monitor_rect->bottom,
15561 "Expected window rect %s, got %s.\n",
15562 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
15564 ret = MoveWindow(window, new_rect.left, new_rect.top, new_rect.right - new_rect.left,
15565 new_rect.bottom - new_rect.top, TRUE);
15566 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
15567 ret = GetWindowRect(window, &window_rect);
15568 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
15569 ok(EqualRect(&window_rect, &new_rect),
15570 "Expected window rect %s, got %s.\n",
15571 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
15572 flush_events();
15573 ret = GetWindowRect(window, &window_rect);
15574 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
15575 ok(window_rect.right != monitor_rect->right && window_rect.bottom != monitor_rect->bottom,
15576 "Expected window rect %s, got %s.\n",
15577 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
15579 /* Window activation should restore the window to fit the whole primary monitor */
15580 ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0,
15581 SWP_NOZORDER | SWP_NOSIZE);
15582 ok(ret, "SetWindowPos failed, error %lu.\n", GetLastError());
15583 ret = SetForegroundWindow(GetDesktopWindow());
15584 ok(ret, "Failed to set foreground window.\n");
15585 flush_events();
15586 ret = ShowWindow(window, SW_RESTORE);
15587 ok(ret, "Failed to restore window, error %lu.\n", GetLastError());
15588 flush_events();
15589 ret = SetForegroundWindow(window);
15590 ok(ret, "SetForegroundWindow failed, error %lu.\n", GetLastError());
15591 flush_events();
15592 ret = GetWindowRect(window, &window_rect);
15593 ok(ret, "GetWindowRect failed, error %lu.\n", GetLastError());
15594 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
15595 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
15597 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
15598 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
15599 ret = GetWindowRect(window, &window_rect);
15600 ok(ret, "GetWindowRect failed, error %lu.\n", GetLastError());
15601 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
15602 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
15604 DestroyWindow(window);
15605 IDirectDraw2_Release(ddraw);
15606 return TRUE;
15609 static void test_window_position(void)
15611 EnumDisplayMonitors(NULL, NULL, test_window_position_cb, 0);
15614 static BOOL CALLBACK test_get_display_mode_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect,
15615 LPARAM lparam)
15617 DDSURFACEDESC surface_desc;
15618 IDirectDraw2 *ddraw;
15619 HWND window;
15620 HRESULT hr;
15621 BOOL ret;
15623 ddraw = create_ddraw();
15624 ok(!!ddraw, "Failed to create a ddraw object.\n");
15625 window = create_window();
15626 ok(!!window, "Failed to create a window.\n");
15628 /* Test that DirectDraw doesn't use the device window to determine which monitor to use */
15629 ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0,
15630 SWP_NOZORDER | SWP_NOSIZE);
15631 ok(ret, "SetWindowPos failed, error %lu.\n", GetLastError());
15633 surface_desc.dwSize = sizeof(surface_desc);
15634 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
15635 ok(hr == DD_OK, "GetDisplayMode failed, hr %#lx.\n", hr);
15636 ok(surface_desc.dwWidth == GetSystemMetrics(SM_CXSCREEN), "Expect width %d, got %lu.\n",
15637 GetSystemMetrics(SM_CXSCREEN), surface_desc.dwWidth);
15638 ok(surface_desc.dwHeight == GetSystemMetrics(SM_CYSCREEN), "Expect height %d, got %lu.\n",
15639 GetSystemMetrics(SM_CYSCREEN), surface_desc.dwHeight);
15641 DestroyWindow(window);
15642 IDirectDraw2_Release(ddraw);
15643 return TRUE;
15646 static void test_get_display_mode(void)
15648 static const DWORD flags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_REFRESHRATE | DDSD_PIXELFORMAT | DDSD_PITCH;
15649 struct find_different_mode_param param;
15650 DDSURFACEDESC surface_desc;
15651 IDirectDraw2 *ddraw;
15652 DEVMODEW devmode;
15653 HWND window;
15654 HRESULT hr;
15655 BOOL ret;
15657 EnumDisplayMonitors(NULL, NULL, test_get_display_mode_cb, 0);
15659 ddraw = create_ddraw();
15660 ok(!!ddraw, "Failed to create a ddraw object.\n");
15661 window = create_window();
15662 ok(!!window, "Failed to create a window.\n");
15664 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
15665 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
15667 memset(&devmode, 0, sizeof(devmode));
15668 devmode.dmSize = sizeof(devmode);
15669 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
15670 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
15672 surface_desc.dwSize = sizeof(surface_desc);
15673 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
15674 ok(hr == DD_OK, "GetDisplayMode failed, hr %#lx.\n", hr);
15675 ok(surface_desc.dwSize == sizeof(surface_desc), "Got dwSize %lu.\n", surface_desc.dwSize);
15676 ok(surface_desc.dwFlags == flags, "Expected dwFlags %#lx, got %#lx.\n", flags,
15677 surface_desc.dwFlags);
15678 ok(surface_desc.dwWidth == devmode.dmPelsWidth, "Expected width %lu, got %lu.\n",
15679 devmode.dmPelsWidth, surface_desc.dwWidth);
15680 ok(surface_desc.dwHeight == devmode.dmPelsHeight, "Expected height %lu, got %lu.\n",
15681 devmode.dmPelsHeight, surface_desc.dwHeight);
15682 ok(surface_desc.dwRefreshRate == devmode.dmDisplayFrequency, "Expected frequency %lu, got %lu.\n",
15683 devmode.dmDisplayFrequency, surface_desc.dwRefreshRate);
15684 ok(surface_desc.ddpfPixelFormat.dwSize == sizeof(surface_desc.ddpfPixelFormat),
15685 "Got ddpfPixelFormat.dwSize %lu.\n", surface_desc.ddpfPixelFormat.dwSize);
15686 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == devmode.dmBitsPerPel,
15687 "Expected ddpfPixelFormat.dwRGBBitCount %lu, got %lu.\n", devmode.dmBitsPerPel,
15688 surface_desc.ddpfPixelFormat.dwRGBBitCount);
15689 ok(surface_desc.lPitch == devmode.dmPelsWidth * devmode.dmBitsPerPel / 8,
15690 "Expected pitch %lu, got %lu.\n", devmode.dmPelsWidth * devmode.dmBitsPerPel / 8,
15691 surface_desc.lPitch);
15693 memset(&param, 0, sizeof(param));
15694 param.old_frequency = surface_desc.dwRefreshRate;
15695 hr = IDirectDraw2_EnumDisplayModes(ddraw, DDEDM_REFRESHRATES, NULL, &param,
15696 find_different_mode_callback);
15697 ok(hr == DD_OK, "EnumDisplayModes failed, hr %#lx.\n", hr);
15698 if (!param.new_frequency)
15700 skip("Failed to find a display mode with a different frequency.\n");
15701 goto done;
15704 hr = IDirectDraw2_SetDisplayMode(ddraw, param.new_width, param.new_height, param.new_bpp,
15705 param.new_frequency, 0);
15706 ok(hr == DD_OK, "SetDisplayMode failed, hr %#lx.\n", hr);
15707 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
15708 ok(hr == DD_OK, "GetDisplayMode failed, hr %#lx.\n", hr);
15709 ok(surface_desc.dwWidth == param.new_width, "Expected width %u, got %lu.\n", param.new_width,
15710 surface_desc.dwWidth);
15711 ok(surface_desc.dwHeight == param.new_height, "Expected height %u, got %lu.\n", param.new_height,
15712 surface_desc.dwHeight);
15713 ok(surface_desc.dwRefreshRate == param.new_frequency, "Expected frequency %u, got %lu.\n",
15714 param.new_frequency, surface_desc.dwRefreshRate);
15715 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == param.new_bpp,
15716 "Expected ddpfPixelFormat.dwRGBBitCount %lu, got %lu.\n", devmode.dmBitsPerPel,
15717 surface_desc.ddpfPixelFormat.dwRGBBitCount);
15719 done:
15720 DestroyWindow(window);
15721 IDirectDraw2_Release(ddraw);
15724 static void test_texture_wrong_caps(const GUID *device_guid)
15726 static D3DLVERTEX quad[] =
15728 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffffffff}, {0}, {0.0f}, {1.0f}},
15729 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}, {0}, {0.0f}, {0.0f}},
15730 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffffffff}, {0}, {1.0f}, {1.0f}},
15731 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}, {0}, {1.0f}, {0.0f}},
15733 static DDPIXELFORMAT fmt =
15735 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
15736 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
15738 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
15739 D3DTEXTUREHANDLE texture_handle, ret_handle;
15740 unsigned int color, expected_color;
15741 IDirectDrawSurface *surface, *rt;
15742 IDirect3DMaterial2 *background;
15743 IDirect3DViewport2 *viewport;
15744 IDirect3DTexture2 *texture;
15745 IDirect3DDevice2 *device;
15746 IDirectDraw2 *ddraw;
15747 DDSURFACEDESC ddsd;
15748 ULONG refcount;
15749 HWND window;
15750 HRESULT hr;
15752 window = create_window();
15753 ddraw = create_ddraw();
15754 ok(!!ddraw, "Failed to create a ddraw object.\n");
15755 if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid, NULL)))
15757 skip("Failed to create a 3D device, skipping test.\n");
15758 DestroyWindow(window);
15759 return;
15761 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
15762 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15764 viewport = create_viewport(device, 0, 0, 640, 480);
15765 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
15766 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15768 memset(&ddsd, 0, sizeof(ddsd));
15769 ddsd.dwSize = sizeof(ddsd);
15770 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
15771 ddsd.dwHeight = 16;
15772 ddsd.dwWidth = 16;
15773 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
15774 ddsd.ddpfPixelFormat = fmt;
15775 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
15776 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
15777 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
15778 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
15779 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
15780 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15782 fill_surface(surface, 0xff00ff00);
15784 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
15785 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15786 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
15787 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15788 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
15789 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15790 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, &ret_handle);
15791 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15792 todo_wine_if (!is_software_device_type(device_guid))
15793 ok(ret_handle == texture_handle, "Got handle %#lx.\n", ret_handle);
15795 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
15796 viewport_set_background(device, viewport, background);
15798 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
15799 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15800 if (is_software_device_type(device_guid))
15801 fill_surface(rt, 0xffff0000);
15803 hr = IDirect3DDevice2_BeginScene(device);
15804 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15805 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, ARRAY_SIZE(quad), 0);
15806 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15807 hr = IDirect3DDevice2_EndScene(device);
15808 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15810 expected_color = is_software_device_type(device_guid) ? 0x0000ff00 : 0x00ffffff;
15811 color = get_surface_color(rt, 320, 240);
15812 ok(compare_color(color, expected_color, 1), "Got color 0x%08x, expected 0x%08x.\n", color, expected_color);
15814 IDirect3DTexture2_Release(texture);
15815 IDirectDrawSurface_Release(surface);
15816 IDirectDrawSurface_Release(rt);
15817 destroy_viewport(device, viewport);
15818 destroy_material(background);
15819 refcount = IDirect3DDevice2_Release(device);
15820 ok(!refcount, "Device has %lu references left.\n", refcount);
15821 IDirectDraw2_Release(ddraw);
15822 DestroyWindow(window);
15825 static void test_filling_convention(void)
15827 IDirectDrawSurface *rt, *backbuffer, *cur, *ds;
15828 static const DWORD colour_bottom = 0x00ffff00;
15829 static const DWORD colour_clear = 0x000000ff;
15830 static const DWORD colour_right = 0x00000000;
15831 static const DWORD colour_left = 0x00ff0000;
15832 static const DWORD colour_top = 0x0000ff00;
15833 unsigned int colour, expected, i, j, x, y;
15834 IDirect3DMaterial2 *background;
15835 IDirect3DViewport2 *viewport;
15836 IDirect3DDevice2 *device;
15837 IDirectDraw2 *ddraw;
15838 DDSURFACEDESC desc;
15839 IDirect3D2 *d3d;
15840 ULONG refcount;
15841 HWND window;
15842 HRESULT hr;
15843 BOOL todo;
15845 static const unsigned int vp_size = 8;
15846 D3DRECT clear_rect = {{0}, {0}, {vp_size}, {vp_size}};
15848 /* This test data follows the examples in MSDN's
15849 * "Rasterization Rules (Direct3D 9)" article.
15851 * See the d3d9 test for a comment about the eps value. */
15852 static const float eps = 1.0f / 64.0f;
15853 D3DLVERTEX center_tris[] =
15855 /* left */
15856 {{-2.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_left}},
15857 {{-2.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_left}},
15858 {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_left}},
15860 /* top */
15861 {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_top}},
15862 {{-2.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_top}},
15863 {{-0.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_top}},
15865 /* right */
15866 {{-0.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_right}},
15867 {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_right}},
15868 {{-0.5f / 4.0f}, { 2.5f / 4.0f}, {0.0f}, 0, {colour_right}},
15870 /* bottom */
15871 {{-2.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15872 {{-1.5f / 4.0f}, { 0.5f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15873 {{-0.5f / 4.0f}, {-1.5f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15875 edge_tris[] =
15877 /* left */
15878 {{-2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15879 {{-2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15880 {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15882 /* top */
15883 {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15884 {{-2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15885 {{ 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15887 /* right */
15888 {{ 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15889 {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15890 {{ 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15892 /* bottom */
15893 {{-2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15894 {{-1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15895 {{ 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15897 nudge_right_tris[] =
15899 /* left */
15900 {{eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15901 {{eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15902 {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15904 /* top */
15905 {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15906 {{eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15907 {{eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15909 /* right */
15910 {{eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15911 {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15912 {{eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15914 /* bottom */
15915 {{eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15916 {{eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15917 {{eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15919 nudge_left_tris[] =
15921 {{-eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15922 {{-eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15923 {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15925 /* top */
15926 {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15927 {{-eps - 2.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15928 {{-eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15930 /* right */
15931 {{-eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15932 {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15933 {{-eps - 0.0f / 4.0f}, { 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15935 /* bottom */
15936 {{-eps - 2.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15937 {{-eps - 1.0f / 4.0f}, { 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15938 {{-eps - 0.0f / 4.0f}, {-1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15940 nudge_top_tris[] =
15942 /* left */
15943 {{-2.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15944 {{-2.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15945 {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15947 /* top */
15948 {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15949 {{-2.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15950 {{ 0.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15952 /* right */
15953 {{ 0.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15954 {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15955 {{ 0.0f / 4.0f}, {eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15957 /* bottom */
15958 {{-2.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15959 {{-1.0f / 4.0f}, {eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15960 {{ 0.0f / 4.0f}, {eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15962 nudge_bottom_tris[] =
15964 /* left */
15965 {{-2.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15966 {{-2.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15967 {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_left}},
15969 /* top */
15970 {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15971 {{-2.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15972 {{ 0.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_top}},
15974 /* right */
15975 {{ 0.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15976 {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15977 {{ 0.0f / 4.0f}, {-eps + 3.0f / 4.0f}, {0.0f}, 0, {colour_right}},
15979 /* bottom */
15980 {{-2.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15981 {{-1.0f / 4.0f}, {-eps + 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15982 {{ 0.0f / 4.0f}, {-eps - 1.0f / 4.0f}, {0.0f}, 0, {colour_bottom}},
15985 D3DTLVERTEX center_tris_t[] =
15987 /* left */
15988 {{1.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_left}},
15989 {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_left}},
15990 {{1.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_left}},
15992 /* top */
15993 {{1.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_top}},
15994 {{3.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_top}},
15995 {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_top}},
15997 /* right */
15998 {{3.5f}, {1.5f}, {0.0f}, {1.0f}, {colour_right}},
15999 {{3.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_right}},
16000 {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_right}},
16002 /* bottom */
16003 {{2.5f}, {3.5f}, {0.0f}, {1.0f}, {colour_bottom}},
16004 {{3.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_bottom}},
16005 {{1.5f}, {5.5f}, {0.0f}, {1.0f}, {colour_bottom}},
16007 edge_tris_t[] =
16009 /* left */
16010 {{2.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_left}},
16011 {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_left}},
16012 {{2.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_left}},
16014 /* top */
16015 {{2.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_top}},
16016 {{4.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_top}},
16017 {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_top}},
16019 /* right */
16020 {{4.0f}, {1.0f}, {0.0f}, {1.0f}, {colour_right}},
16021 {{4.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_right}},
16022 {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_right}},
16024 /* bottom */
16025 {{3.0f}, {3.0f}, {0.0f}, {1.0f}, {colour_bottom}},
16026 {{4.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_bottom}},
16027 {{2.0f}, {5.0f}, {0.0f}, {1.0f}, {colour_bottom}},
16030 const struct
16032 void *geometry;
16033 DWORD fvf;
16034 const char *expected[8];
16036 tests[] =
16039 center_tris,
16040 D3DVT_LVERTEX,
16042 " ",
16043 " ",
16044 " TT ",
16045 " LR ",
16046 " LR ",
16047 " BB ",
16048 " ",
16053 edge_tris,
16054 D3DVT_LVERTEX,
16056 " ",
16057 " TT ",
16058 " LT ",
16059 " LR ",
16060 " LB ",
16061 " ",
16062 " ",
16067 nudge_right_tris,
16068 D3DVT_LVERTEX,
16070 " ",
16071 " TT ",
16072 " TR ",
16073 " LR ",
16074 " BR ",
16075 " ",
16076 " ",
16081 nudge_left_tris,
16082 D3DVT_LVERTEX,
16084 " ",
16085 " TT ",
16086 " LT ",
16087 " LR ",
16088 " LB ",
16089 " ",
16090 " ",
16095 nudge_top_tris,
16096 D3DVT_LVERTEX,
16098 " ",
16099 " LT ",
16100 " LT ",
16101 " LB ",
16102 " LB ",
16103 " ",
16104 " ",
16109 nudge_bottom_tris,
16110 D3DVT_LVERTEX,
16112 " ",
16113 " ",
16114 " LT ",
16115 " Lt ",
16116 " LB ",
16117 " lB ",
16118 " ",
16123 center_tris_t,
16124 D3DVT_TLVERTEX,
16126 " ",
16127 " ",
16128 " TT ",
16129 " LR ",
16130 " LR ",
16131 " BB ",
16132 " ",
16137 edge_tris_t,
16138 D3DVT_TLVERTEX,
16140 " ",
16141 " TT ",
16142 " LT ",
16143 " LR ",
16144 " LB ",
16145 " ",
16146 " ",
16152 window = create_window();
16153 ddraw = create_ddraw();
16154 ok(!!ddraw, "Failed to create a ddraw object.\n");
16155 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
16157 skip("Failed to create a 3D device.\n");
16158 IDirectDraw2_Release(ddraw);
16159 DestroyWindow(window);
16160 return;
16163 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
16164 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16165 hr = IDirect3DDevice2_GetRenderTarget(device, &backbuffer);
16166 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16168 viewport = create_viewport(device, 0, 0, vp_size, vp_size);
16169 background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
16170 viewport_set_background(device, viewport, background);
16171 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
16172 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16174 memset(&desc, 0, sizeof(desc));
16175 desc.dwSize = sizeof(desc);
16176 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
16177 desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
16178 desc.dwWidth = vp_size;
16179 desc.dwHeight = vp_size;
16180 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
16181 desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
16182 desc.ddpfPixelFormat.dwRGBBitCount = 32;
16183 desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
16184 desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
16185 desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
16186 hr = IDirectDraw2_CreateSurface(ddraw, &desc, &rt, NULL);
16187 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16189 /* Nvidia on Windows 10 refuses to set the offscreen RT
16190 * if it does not have an attached depth stencil. */
16191 ds = get_depth_stencil(device);
16192 memset(&desc, 0, sizeof(desc));
16193 desc.dwSize = sizeof(desc);
16194 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
16195 hr = IDirectDrawSurface_GetPixelFormat(ds, &desc.ddpfPixelFormat);
16196 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16197 IDirectDrawSurface4_Release(ds);
16199 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
16200 desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
16201 desc.dwWidth = vp_size;
16202 desc.dwHeight = vp_size;
16203 hr = IDirectDraw2_CreateSurface(ddraw, &desc, &ds, NULL);
16204 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16205 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
16206 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#lx.\n", hr);
16208 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
16209 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16210 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
16211 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16213 for (i = 0; i < ARRAY_SIZE(tests); ++i)
16215 for (j = 0; j < 2; ++j)
16217 cur = j ? rt : backbuffer;
16219 hr = IDirect3DDevice2_SetRenderTarget(device, cur, 0);
16220 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16221 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
16222 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16224 hr = IDirect3DDevice2_BeginScene(device);
16225 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16226 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLELIST,
16227 tests[i].fvf, tests[i].geometry, 12, 0);
16228 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16229 hr = IDirect3DDevice2_EndScene(device);
16230 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16232 for (y = 0; y < 8; y++)
16234 for (x = 0; x < 8; x++)
16236 todo = FALSE;
16237 switch (tests[i].expected[y][x])
16239 case 'l': todo = TRUE;
16240 case 'L':
16241 expected = colour_left;
16242 break;
16243 case 't': todo = TRUE;
16244 case 'T':
16245 expected = colour_top;
16246 break;
16247 case 'r': todo = TRUE;
16248 case 'R':
16249 expected = colour_right;
16250 break;
16251 case 'b': todo = TRUE;
16252 case 'B':
16253 expected = colour_bottom;
16254 break;
16255 case ' ':
16256 expected = colour_clear;
16257 break;
16258 default:
16259 ok(0, "Unexpected entry in expected test char\n");
16260 expected = 0xdeadbeef;
16262 colour = get_surface_color(cur, x, y);
16263 /* The nudge-to-bottom test fails on cards that give us a bottom-left
16264 * filling convention. The cause isn't the bottom part of the filling
16265 * convention, but because wined3d will nudge geometry to the left to
16266 * keep diagonals (the 'R' in test case 'edge_tris') intact. */
16267 todo_wine_if(todo && !compare_color(colour, expected, 1))
16268 ok(compare_color(colour, expected, 1), "Got unexpected colour %08x, %ux%u, case %u, j %u.\n",
16269 colour, x, y, i, j);
16275 destroy_viewport(device, viewport);
16276 IDirectDrawSurface_Release(backbuffer);
16277 IDirectDrawSurface_Release(rt);
16278 IDirectDrawSurface_Release(ds);
16279 IDirect3D2_Release(d3d);
16280 refcount = IDirect3DDevice2_Release(device);
16281 ok(!refcount, "Device has %lu references left.\n", refcount);
16282 refcount = IDirectDraw2_Release(ddraw);
16283 ok(!refcount, "Device has %lu references left.\n", refcount);
16284 DestroyWindow(window);
16287 static HRESULT WINAPI test_enum_devices_caps_callback(GUID *guid, char *device_desc,
16288 char *device_name, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, void *ctx)
16290 if(IsEqualGUID(&IID_IDirect3DRGBDevice, guid))
16292 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
16293 "RGB Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n");
16294 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
16295 "RGB Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n");
16296 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
16297 "RGB Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
16298 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
16299 "RGB Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
16301 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
16302 "RGB Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
16303 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
16304 "RGB Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
16305 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
16306 "RGB Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
16307 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
16308 "RGB Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
16310 ok(hal->dcmColorModel == 0, "RGB Device hal caps has colormodel %lu\n", hal->dcmColorModel);
16311 ok(hel->dcmColorModel == D3DCOLOR_RGB, "RGB Device hel caps has colormodel %lu\n", hel->dcmColorModel);
16313 ok(hal->dwFlags == 0, "RGB Device hal caps has hardware flags %#lx\n", hal->dwFlags);
16314 ok(hel->dwFlags != 0, "RGB Device hel caps has hardware flags %#lx\n", hel->dwFlags);
16316 ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
16317 "RGB Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
16318 ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
16319 "RGB Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
16320 ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
16321 "RGB Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
16322 ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
16323 "RGB Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
16324 ok((hal->dwDevCaps & D3DDEVCAPS_HWRASTERIZATION) == 0,
16325 "RGB Device hal device caps has D3DDEVCAPS_HWRASTERIZATION set\n");
16326 ok((hel->dwDevCaps & D3DDEVCAPS_HWRASTERIZATION) == 0,
16327 "RGB Device hel device caps has D3DDEVCAPS_HWRASTERIZATION set\n");
16329 else if(IsEqualGUID(&IID_IDirect3DHALDevice, guid))
16331 ok(hal->dcmColorModel == D3DCOLOR_RGB, "HAL Device hal caps has colormodel %lu\n", hel->dcmColorModel);
16332 ok(hel->dcmColorModel == 0, "HAL Device hel caps has colormodel %lu\n", hel->dcmColorModel);
16334 ok(hal->dwFlags != 0, "HAL Device hal caps has hardware flags %#lx\n", hal->dwFlags);
16335 ok(hel->dwFlags != 0, "HAL Device hel caps has hardware flags %#lx\n", hel->dwFlags);
16337 ok(hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT,
16338 "HAL Device hal device caps does not have D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
16339 ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
16340 "RGB Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
16341 ok(hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX,
16342 "HAL Device hal device caps does not have D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
16343 ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
16344 "RGB Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
16346 else if(IsEqualGUID(&IID_IDirect3DRefDevice, guid))
16348 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
16349 "REF Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n");
16350 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
16351 "REF Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n");
16352 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
16353 "REF Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
16354 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
16355 "REF Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
16357 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
16358 "REF Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
16359 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
16360 "REF Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
16361 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
16362 "REF Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
16363 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
16364 "REF Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
16366 ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
16367 "REF Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
16368 ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
16369 "REF Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
16370 ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
16371 "REF Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
16372 ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
16373 "REF Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
16375 else if(IsEqualGUID(&IID_IDirect3DRampDevice, guid))
16377 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
16378 "Ramp Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n");
16379 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
16380 "Ramp Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n");
16381 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
16382 "Ramp Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
16383 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
16384 "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
16386 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
16387 "Ramp Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
16388 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
16389 "Ramp Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
16390 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
16391 "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
16392 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
16393 "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
16395 ok(hal->dcmColorModel == 0, "Ramp Device hal caps has colormodel %lu\n", hal->dcmColorModel);
16396 ok(hel->dcmColorModel == D3DCOLOR_MONO, "Ramp Device hel caps has colormodel %lu\n",
16397 hel->dcmColorModel);
16399 ok(hal->dwFlags == 0, "Ramp Device hal caps has hardware flags %#lx\n", hal->dwFlags);
16400 ok(hel->dwFlags != 0, "Ramp Device hel caps has hardware flags %#lx\n", hel->dwFlags);
16402 ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
16403 "Ramp Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
16404 ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
16405 "Ramp Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
16406 ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
16407 "Ramp Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
16408 ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
16409 "Ramp Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
16411 else if(IsEqualGUID(&IID_IDirect3DMMXDevice, guid))
16413 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
16414 "MMX Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n");
16415 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
16416 "MMX Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n");
16417 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
16418 "MMX Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
16419 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
16420 "MMX Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
16422 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
16423 "MMX Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
16424 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
16425 "MMX Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
16426 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
16427 "MMX Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
16428 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
16429 "MMX Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
16431 ok(hal->dcmColorModel == 0, "MMX Device hal caps has colormodel %lu\n", hal->dcmColorModel);
16432 ok(hel->dcmColorModel == D3DCOLOR_RGB, "MMX Device hel caps has colormodel %lu\n", hel->dcmColorModel);
16434 ok(hal->dwFlags == 0, "MMX Device hal caps has hardware flags %#lx\n", hal->dwFlags);
16435 ok(hel->dwFlags != 0, "MMX Device hel caps has hardware flags %#lx\n", hel->dwFlags);
16437 ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
16438 "MMX Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
16439 ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
16440 "MMX Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
16441 ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
16442 "MMX Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
16443 ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
16444 "MMX Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
16446 else
16448 ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", device_desc, device_name);
16449 if (hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)
16450 trace("hal line has pow2 set\n");
16451 else
16452 trace("hal line does NOT have pow2 set\n");
16453 if (hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)
16454 trace("hal tri has pow2 set\n");
16455 else
16456 trace("hal tri does NOT have pow2 set\n");
16457 if (hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)
16458 trace("hel line has pow2 set\n");
16459 else
16460 trace("hel line does NOT have pow2 set\n");
16461 if (hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)
16462 trace("hel tri has pow2 set\n");
16463 else
16464 trace("hel tri does NOT have pow2 set\n");
16467 return DDENUMRET_OK;
16470 static void test_enum_devices(void)
16472 IDirectDraw2 *ddraw;
16473 IDirect3D2 *d3d;
16474 ULONG refcount;
16475 HRESULT hr;
16477 ddraw = create_ddraw();
16478 ok(!!ddraw, "Failed to create a ddraw object.\n");
16480 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
16481 if (FAILED(hr))
16483 skip("D3D interface is not available, skipping test.\n");
16484 IDirectDraw2_Release(ddraw);
16485 return;
16488 hr = IDirect3D2_EnumDevices(d3d, NULL, NULL);
16489 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
16491 hr = IDirect3D2_EnumDevices(d3d, test_enum_devices_caps_callback, NULL);
16492 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
16494 IDirect3D2_Release(d3d);
16495 refcount = IDirectDraw2_Release(ddraw);
16496 ok(!refcount, "Device has %lu references left.\n", refcount);
16499 static void run_for_each_device_type(void (*test_func)(const GUID *))
16501 test_func(&IID_IDirect3DHALDevice);
16502 test_func(&IID_IDirect3DRGBDevice);
16505 static void test_multiple_devices(void)
16507 D3DTEXTUREHANDLE texture_handle, texture_handle2;
16508 IDirect3DDevice2 *device, *device2, *device3;
16509 IDirectDrawSurface *surface, *texture_surf;
16510 D3DMATERIALHANDLE mat_handle, mat_handle2;
16511 IDirect3DViewport2 *viewport, *viewport2;
16512 IDirectDraw2 *ddraw, *ddraw2;
16513 IDirect3DMaterial2 *material;
16514 DDSURFACEDESC surface_desc;
16515 IDirect3DTexture2 *texture;
16516 IDirect3D2 *d3d;
16517 ULONG refcount;
16518 DWORD value;
16519 HWND window;
16520 HRESULT hr;
16522 window = create_window();
16523 ddraw = create_ddraw();
16524 ok(!!ddraw, "Failed to create a ddraw object.\n");
16526 if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, &IID_IDirect3DHALDevice, &surface)))
16528 skip("Failed to create a 3D device, skipping test.\n");
16529 DestroyWindow(window);
16530 return;
16533 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
16534 ok(hr == D3D_OK, "got %#lx.\n", hr);
16535 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device2);
16536 ok(hr == D3D_OK, "got %#lx.\n", hr);
16538 ddraw2 = create_ddraw();
16539 ok(!!ddraw2, "Failed to create a ddraw object.\n");
16540 device3 = create_device(ddraw2, window, DDSCL_NORMAL);
16541 ok(!!device3, "got NULL.\n");
16543 viewport = create_viewport(device, 0, 0, 640, 480);
16544 viewport2 = create_viewport(device2, 0, 0, 640, 480);
16545 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
16546 ok(hr == D3D_OK, "got %#lx.\n", hr);
16547 hr = IDirect3DDevice2_SetCurrentViewport(device2, viewport);
16548 ok(hr == DDERR_INVALIDPARAMS, "got %#lx.\n", hr);
16549 hr = IDirect3DDevice2_SetCurrentViewport(device2, viewport2);
16550 ok(hr == D3D_OK, "got %#lx.\n", hr);
16552 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
16553 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
16554 ok(hr == D3D_OK, "got %#lx.\n", hr);
16555 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle2);
16556 ok(hr == D3D_OK, "got %#lx.\n", hr);
16557 ok(mat_handle == mat_handle2, "got different handles.\n");
16559 hr = IDirect3DMaterial2_GetHandle(material, device2, &mat_handle2);
16560 ok(hr == D3D_OK, "got %#lx.\n", hr);
16561 todo_wine ok(mat_handle != mat_handle2, "got same handles.\n");
16563 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
16564 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16565 hr = IDirect3DDevice2_SetLightState(device2, D3DLIGHTSTATE_MATERIAL, mat_handle);
16566 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16567 hr = IDirect3DDevice2_SetLightState(device3, D3DLIGHTSTATE_MATERIAL, mat_handle);
16568 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16569 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle2);
16570 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16572 hr = IDirect3DViewport2_SetBackground(viewport, mat_handle);
16573 ok(hr == D3D_OK, "got %#lx.\n", hr);
16574 hr = IDirect3DViewport2_SetBackground(viewport2, mat_handle);
16575 ok(hr == D3D_OK, "got %#lx.\n", hr);
16577 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
16578 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16579 hr = IDirect3DDevice2_SetRenderState(device2, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
16580 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16581 hr = IDirect3DDevice2_SetRenderState(device3, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
16582 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16584 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
16585 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16586 value = 0xdeadbeef;
16587 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
16588 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16589 ok(value == TRUE, "got %#lx.\n", value);
16590 hr = IDirect3DDevice2_GetRenderState(device2, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
16591 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16592 ok(!value, "got %#lx.\n", value);
16593 hr = IDirect3DDevice2_GetRenderState(device3, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
16594 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16595 ok(!value, "got %#lx.\n", value);
16597 memset(&surface_desc, 0, sizeof(surface_desc));
16598 surface_desc.dwSize = sizeof(surface_desc);
16599 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
16600 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
16601 surface_desc.dwWidth = 256;
16602 surface_desc.dwHeight = 256;
16603 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &texture_surf, NULL);
16604 ok(hr == D3D_OK, "got %#lx.\n", hr);
16605 hr = IDirectDrawSurface_QueryInterface(texture_surf, &IID_IDirect3DTexture2, (void **)&texture);
16606 ok(hr == D3D_OK, "got %#lx.\n", hr);
16607 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
16608 ok(hr == D3D_OK, "got %#lx.\n", hr);
16609 hr = IDirect3DTexture2_GetHandle(texture, device2, &texture_handle2);
16610 ok(hr == D3D_OK, "got %#lx.\n", hr);
16611 ok(texture_handle == texture_handle2, "got different handles.\n");
16612 hr = IDirect3DTexture2_GetHandle(texture, device3, &texture_handle2);
16613 ok(hr == D3D_OK, "got %#lx.\n", hr);
16614 ok(texture_handle == texture_handle2, "got different handles.\n");
16615 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
16616 ok(hr == D3D_OK, "got %#lx.\n", hr);
16617 hr = IDirect3DDevice2_SetRenderState(device2, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
16618 ok(hr == D3D_OK, "got %#lx.\n", hr);
16619 hr = IDirect3DDevice2_SetRenderState(device3, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
16620 ok(hr == D3D_OK, "got %#lx.\n", hr);
16622 IDirect3DTexture2_Release(texture);
16623 IDirectDrawSurface_Release(texture_surf);
16624 IDirect3DMaterial2_Release(material);
16625 IDirect3DViewport2_Release(viewport);
16626 IDirect3DViewport2_Release(viewport2);
16628 refcount = IDirect3DDevice2_Release(device);
16629 ok(!refcount, "Device has %lu references left.\n", refcount);
16630 refcount = IDirect3DDevice2_Release(device2);
16631 ok(!refcount, "Device has %lu references left.\n", refcount);
16632 refcount = IDirect3DDevice2_Release(device3);
16633 ok(!refcount, "Device has %lu references left.\n", refcount);
16634 refcount = IDirectDrawSurface_Release(surface);
16635 ok(!refcount, "Surface has %lu references left.\n", refcount);
16637 IDirectDraw2_Release(ddraw);
16638 IDirectDraw_Release(ddraw2);
16639 IDirect3D2_Release(d3d);
16640 DestroyWindow(window);
16643 static void test_d3d_state_reset(void)
16645 struct find_different_mode_param param;
16646 IDirect3DViewport2 *viewport;
16647 IDirectDrawSurface *surface;
16648 IDirect3DDevice2 *device;
16649 D3DVIEWPORT2 vp1, vp2;
16650 IDirectDraw2 *ddraw;
16651 DDSURFACEDESC ddsd;
16652 DWORD state;
16653 HWND window;
16654 HRESULT hr;
16656 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, 0, 0);
16658 window = create_window();
16659 ddraw = create_ddraw();
16660 ok(!!ddraw, "Failed to create a ddraw object.\n");
16662 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
16664 skip("Failed to create 3D device.\n");
16665 DestroyWindow(window);
16666 return;
16669 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x00282828);
16670 ok(hr == DD_OK, "got %#lx.\n", hr);
16671 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, TRUE);
16672 ok(hr == DD_OK, "got %#lx.\n", hr);
16674 memset(&param, 0, sizeof(param));
16675 hr = IDirectDraw2_EnumDisplayModes(ddraw, 0, NULL, &param, find_different_mode_callback);
16676 ok(hr == DD_OK, "got %#lx.\n", hr);
16678 viewport = create_viewport(device, 0, 0, param.old_width, param.old_height);
16679 ok(hr == DD_OK, "got %#lx.\n", hr);
16681 vp1.dwSize = sizeof(vp1);
16682 vp2.dwSize = sizeof(vp2);
16684 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
16685 ok(hr == DD_OK, "got %#lx.\n", hr);
16686 hr = IDirect3DViewport2_GetViewport2(viewport, &vp1);
16687 ok(hr == DD_OK, "got %#lx.\n", hr);
16689 hr = set_display_mode(ddraw, param.new_width, param.new_height);
16690 ok(hr == DD_OK, "got %#lx.\n", hr);
16692 hr = IDirect3DViewport2_GetViewport2(viewport, &vp2);
16693 ok(hr == DD_OK, "got %#lx.\n", hr);
16694 ok(vp2.dwWidth == vp1.dwWidth, "got %ld, expected %ld.\n", vp2.dwWidth, vp1.dwWidth);
16695 ok(vp2.dwHeight == vp1.dwHeight, "got %ld, expected %ld.\n", vp2.dwHeight, vp1.dwHeight);
16697 memset(&ddsd, 0, sizeof(ddsd));
16698 ddsd.dwSize = sizeof(ddsd);
16699 ddsd.dwFlags = DDSD_CAPS;
16700 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
16702 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
16703 ok(hr == DD_OK, "got %#lx.\n", hr);
16705 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
16706 ok(hr == DD_OK, "got %#lx.\n", hr);
16707 ok(ddsd.dwWidth == param.new_width, "got %ld, expected %d.\n", ddsd.dwWidth, param.new_width);
16708 ok(ddsd.dwHeight == param.new_height, "got %ld, expected %d.\n", ddsd.dwHeight, param.new_height);
16710 hr = IDirect3DViewport2_GetViewport2(viewport, &vp2);
16711 ok(hr == DD_OK, "got %#lx.\n", hr);
16712 ok(vp2.dwWidth == vp1.dwWidth, "got %ld, expected %ld.\n", vp2.dwWidth, vp1.dwWidth);
16713 ok(vp2.dwHeight == vp1.dwHeight, "got %ld, expected %ld.\n", vp2.dwHeight, vp1.dwHeight);
16715 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_FOGCOLOR, &state);
16716 ok(hr == DD_OK, "got %#lx.\n", hr);
16717 ok(state == 0x00282828, "got %#lx.\n", state);
16718 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &state);
16719 ok(hr == DD_OK, "got %#lx.\n", hr);
16720 ok(state == TRUE, "got %#lx.\n", state);
16722 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
16723 ok(hr == DD_OK, "got %#lx.\n", hr);
16725 IDirect3DViewport2_Release(viewport);
16726 IDirectDrawSurface_Release(surface);
16727 IDirectDraw2_Release(ddraw);
16728 IDirect3DDevice2_Release(device);
16729 DestroyWindow(window);
16732 START_TEST(ddraw2)
16734 DDDEVICEIDENTIFIER identifier;
16735 DEVMODEW current_mode;
16736 IDirectDraw2 *ddraw;
16737 HMODULE dwmapi;
16739 if (!(ddraw = create_ddraw()))
16741 skip("Failed to create a ddraw object, skipping tests.\n");
16742 return;
16745 if (ddraw_get_identifier(ddraw, &identifier))
16747 trace("Driver string: \"%s\"\n", identifier.szDriver);
16748 trace("Description string: \"%s\"\n", identifier.szDescription);
16749 trace("Driver version %d.%d.%d.%d\n",
16750 HIWORD(identifier.liDriverVersion.HighPart), LOWORD(identifier.liDriverVersion.HighPart),
16751 HIWORD(identifier.liDriverVersion.LowPart), LOWORD(identifier.liDriverVersion.LowPart));
16753 IDirectDraw2_Release(ddraw);
16755 memset(&current_mode, 0, sizeof(current_mode));
16756 current_mode.dmSize = sizeof(current_mode);
16757 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
16758 registry_mode.dmSize = sizeof(registry_mode);
16759 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
16760 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
16761 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
16763 skip("Current mode does not match registry mode, skipping test.\n");
16764 return;
16767 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
16768 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
16770 test_coop_level_create_device_window();
16771 test_clipper_blt();
16772 test_coop_level_d3d_state();
16773 test_surface_interface_mismatch();
16774 test_coop_level_threaded();
16775 run_for_each_device_type(test_depth_blit);
16776 test_texture_load_ckey();
16777 test_viewport_object();
16778 run_for_each_device_type(test_zenable);
16779 run_for_each_device_type(test_ck_rgba);
16780 test_ck_default();
16781 test_ck_complex();
16782 test_surface_qi();
16783 test_device_qi();
16784 test_wndproc();
16785 test_window_style();
16786 test_redundant_mode_set();
16787 test_coop_level_mode_set();
16788 test_coop_level_mode_set_multi();
16789 test_initialize();
16790 test_coop_level_surf_create();
16791 test_coop_level_multi_window();
16792 test_clear_rect_count();
16793 test_coop_level_versions();
16794 test_lighting_interface_versions();
16795 test_coop_level_activateapp();
16796 test_unsupported_formats();
16797 run_for_each_device_type(test_rt_caps);
16798 test_primary_caps();
16799 test_surface_lock();
16800 test_surface_discard();
16801 test_flip();
16802 test_set_surface_desc();
16803 test_user_memory_getdc();
16804 test_sysmem_overlay();
16805 test_primary_palette();
16806 test_surface_attachment();
16807 test_pixel_format();
16808 test_create_surface_pitch();
16809 test_mipmap();
16810 test_palette_complex();
16811 test_p8_blit();
16812 test_material();
16813 test_lighting();
16814 test_specular_lighting();
16815 test_palette_gdi();
16816 test_palette_alpha();
16817 test_lost_device();
16818 test_surface_desc_lock();
16819 test_texturemapblend();
16820 test_viewport_clear_rect();
16821 test_color_fill();
16822 test_colorkey_precision();
16823 test_range_colorkey();
16824 test_shademode();
16825 test_lockrect_invalid();
16826 test_yv12_overlay();
16827 test_offscreen_overlay();
16828 test_overlay_rect();
16829 test_blt();
16830 test_blt_z_alpha();
16831 test_cross_device_blt();
16832 test_getdc();
16833 test_draw_primitive();
16834 test_edge_antialiasing_blending();
16835 test_transform_vertices();
16836 test_display_mode_surface_pixel_format();
16837 test_surface_desc_size();
16838 test_ck_operation();
16839 test_set_render_state();
16840 test_depth_readback();
16841 test_clear();
16842 test_enum_surfaces();
16843 test_viewport();
16844 test_find_device();
16845 test_killfocus();
16846 test_gdi_surface();
16847 test_alphatest();
16848 test_clipper_refcount();
16849 test_caps();
16850 test_d32_support();
16851 test_cursor_clipping();
16852 test_window_position();
16853 test_get_display_mode();
16854 run_for_each_device_type(test_texture_wrong_caps);
16855 test_filling_convention();
16856 test_enum_devices();
16857 test_multiple_devices();
16858 test_d3d_state_reset();