ddraw/tests: Run test_depth_blit() for each device type.
[wine.git] / dlls / ddraw / tests / ddraw2.c
blob4e6392b51f7261f367b7310e4f4b5574e98c932b
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 "wine/heap.h"
26 #include <limits.h>
27 #include <math.h>
28 #include "ddrawi.h"
29 #include "d3dhal.h"
31 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
32 static DEVMODEW registry_mode;
34 static HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *);
36 struct vec2
38 float x, y;
41 struct vec4
43 float x, y, z, w;
46 struct create_window_thread_param
48 HWND window;
49 HANDLE window_created;
50 HANDLE destroy_window;
51 HANDLE thread;
54 static BOOL compare_float(float f, float g, unsigned int ulps)
56 int x = *(int *)&f;
57 int y = *(int *)&g;
59 if (x < 0)
60 x = INT_MIN - x;
61 if (y < 0)
62 y = INT_MIN - y;
64 if (abs(x - y) > ulps)
65 return FALSE;
67 return TRUE;
70 static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
72 return compare_float(vec->x, x, ulps)
73 && compare_float(vec->y, y, ulps)
74 && compare_float(vec->z, z, ulps)
75 && compare_float(vec->w, w, ulps);
78 static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff)
80 unsigned int diff = x > y ? x - y : y - x;
82 return diff <= max_diff;
85 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
87 return compare_uint(c1 & 0xff, c2 & 0xff, max_diff)
88 && compare_uint((c1 >> 8) & 0xff, (c2 >> 8) & 0xff, max_diff)
89 && compare_uint((c1 >> 16) & 0xff, (c2 >> 16) & 0xff, max_diff)
90 && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff);
93 static void get_virtual_rect(RECT *rect)
95 rect->left = GetSystemMetrics(SM_XVIRTUALSCREEN);
96 rect->top = GetSystemMetrics(SM_YVIRTUALSCREEN);
97 rect->right = rect->left + GetSystemMetrics(SM_CXVIRTUALSCREEN);
98 rect->bottom = rect->top + GetSystemMetrics(SM_CYVIRTUALSCREEN);
101 /* Try to make sure pending X events have been processed before continuing */
102 static void flush_events(void)
104 int diff = 200;
105 DWORD time;
106 MSG msg;
108 time = GetTickCount() + diff;
109 while (diff > 0)
111 if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT)
112 break;
113 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
114 DispatchMessageA(&msg);
115 diff = time - GetTickCount();
119 static BOOL ddraw_get_identifier(IDirectDraw2 *ddraw, DDDEVICEIDENTIFIER *identifier)
121 IDirectDraw4 *ddraw4;
122 HRESULT hr;
124 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirectDraw4, (void **)&ddraw4);
125 ok(SUCCEEDED(hr), "Failed to get IDirectDraw4 interface, hr %#x.\n", hr);
126 hr = IDirectDraw4_GetDeviceIdentifier(ddraw4, identifier, 0);
127 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
128 IDirectDraw4_Release(ddraw4);
130 return SUCCEEDED(hr);
133 static BOOL ddraw_is_warp(IDirectDraw2 *ddraw)
135 DDDEVICEIDENTIFIER identifier;
137 return strcmp(winetest_platform, "wine")
138 && ddraw_get_identifier(ddraw, &identifier)
139 && strstr(identifier.szDriver, "warp");
142 static BOOL ddraw_is_vendor(IDirectDraw2 *ddraw, DWORD vendor)
144 DDDEVICEIDENTIFIER identifier;
146 return strcmp(winetest_platform, "wine")
147 && ddraw_get_identifier(ddraw, &identifier)
148 && identifier.dwVendorId == vendor;
151 static BOOL ddraw_is_intel(IDirectDraw2 *ddraw)
153 return ddraw_is_vendor(ddraw, 0x8086);
156 static BOOL ddraw_is_nvidia(IDirectDraw2 *ddraw)
158 return ddraw_is_vendor(ddraw, 0x10de);
161 static BOOL ddraw_is_vmware(IDirectDraw2 *ddraw)
163 return ddraw_is_vendor(ddraw, 0x15ad);
166 static BOOL is_software_device_type(const GUID *device_guid)
168 return device_guid != &IID_IDirect3DHALDevice;
171 static IDirectDrawSurface *create_overlay(IDirectDraw2 *ddraw,
172 unsigned int width, unsigned int height, DWORD format)
174 IDirectDrawSurface *surface;
175 DDSURFACEDESC desc;
177 memset(&desc, 0, sizeof(desc));
178 desc.dwSize = sizeof(desc);
179 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
180 desc.dwWidth = width;
181 desc.dwHeight = height;
182 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
183 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
184 desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
185 desc.ddpfPixelFormat.dwFourCC = format;
187 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &desc, &surface, NULL)))
188 return NULL;
189 return surface;
192 static HWND create_window(void)
194 RECT r = {0, 0, 640, 480};
196 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
198 return CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
199 CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
202 static DWORD WINAPI create_window_thread_proc(void *param)
204 struct create_window_thread_param *p = param;
205 DWORD res;
206 BOOL ret;
208 p->window = create_window();
209 ret = SetEvent(p->window_created);
210 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
212 for (;;)
214 MSG msg;
216 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
217 DispatchMessageA(&msg);
218 res = WaitForSingleObject(p->destroy_window, 100);
219 if (res == WAIT_OBJECT_0)
220 break;
221 if (res != WAIT_TIMEOUT)
223 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
224 break;
228 DestroyWindow(p->window);
230 return 0;
233 static void create_window_thread(struct create_window_thread_param *p)
235 DWORD res, tid;
237 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
238 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
239 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
240 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
241 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
242 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
243 res = WaitForSingleObject(p->window_created, INFINITE);
244 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
247 static void destroy_window_thread(struct create_window_thread_param *p)
249 SetEvent(p->destroy_window);
250 WaitForSingleObject(p->thread, INFINITE);
251 CloseHandle(p->destroy_window);
252 CloseHandle(p->window_created);
253 CloseHandle(p->thread);
256 static IDirectDrawSurface *get_depth_stencil(IDirect3DDevice2 *device)
258 IDirectDrawSurface *rt, *ret;
259 DDSCAPS caps = {DDSCAPS_ZBUFFER};
260 HRESULT hr;
262 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
263 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
264 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ret);
265 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
266 IDirectDrawSurface_Release(rt);
267 return ret;
270 /* Free original_modes after finished using it */
271 static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
273 unsigned int number, size = 2, count = 0, index = 0;
274 DISPLAY_DEVICEW display_device;
275 DEVMODEW *modes, *tmp;
277 if (!(modes = heap_alloc(size * sizeof(*modes))))
278 return FALSE;
280 display_device.cb = sizeof(display_device);
281 while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
283 /* Skip software devices */
284 if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
285 continue;
287 if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
288 continue;
290 if (count >= size)
292 size *= 2;
293 if (!(tmp = heap_realloc(modes, size * sizeof(*modes))))
295 heap_free(modes);
296 return FALSE;
298 modes = tmp;
301 memset(&modes[count], 0, sizeof(modes[count]));
302 modes[count].dmSize = sizeof(modes[count]);
303 if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
305 heap_free(modes);
306 return FALSE;
309 lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
312 *original_modes = modes;
313 *display_count = count;
314 return TRUE;
317 static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
319 unsigned int index;
320 LONG ret;
322 for (index = 0; index < count; ++index)
324 ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
325 CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
326 if (ret != DISP_CHANGE_SUCCESSFUL)
327 return FALSE;
329 ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
330 return ret == DISP_CHANGE_SUCCESSFUL;
333 static HRESULT set_display_mode(IDirectDraw2 *ddraw, DWORD width, DWORD height)
335 if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
336 return DD_OK;
337 return IDirectDraw2_SetDisplayMode(ddraw, width, height, 24, 0, 0);
340 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
342 RECT rect = {x, y, x + 1, y + 1};
343 DDSURFACEDESC surface_desc;
344 D3DCOLOR color;
345 HRESULT hr;
347 memset(&surface_desc, 0, sizeof(surface_desc));
348 surface_desc.dwSize = sizeof(surface_desc);
350 hr = IDirectDrawSurface_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
351 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
352 if (FAILED(hr))
353 return 0xdeadbeef;
355 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
357 hr = IDirectDrawSurface_Unlock(surface, NULL);
358 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
360 return color;
363 static void fill_surface(IDirectDrawSurface *surface, D3DCOLOR color)
365 DDSURFACEDESC surface_desc = {sizeof(surface_desc)};
366 HRESULT hr;
367 unsigned int x, y;
368 DWORD *ptr;
370 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
371 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
373 for (y = 0; y < surface_desc.dwHeight; ++y)
375 ptr = (DWORD *)((BYTE *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
376 for (x = 0; x < surface_desc.dwWidth; ++x)
378 ptr[x] = color;
382 hr = IDirectDrawSurface_Unlock(surface, NULL);
383 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
386 static void check_rect(IDirectDrawSurface *surface, RECT r, const char *message)
388 LONG x_coords[2][2] =
390 {r.left - 1, r.left + 1},
391 {r.right + 1, r.right - 1},
393 LONG y_coords[2][2] =
395 {r.top - 1, r.top + 1},
396 {r.bottom + 1, r.bottom - 1}
398 unsigned int i, j, x_side, y_side;
399 DWORD 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 DWORD 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, "%s: Pixel (%d, %d) has color %08x, expected %08x\n",
418 message, x, y, color, expected);
425 static DWORD get_device_z_depth(IDirect3DDevice2 *device)
427 DDSCAPS caps = {DDSCAPS_ZBUFFER};
428 IDirectDrawSurface *ds, *rt;
429 DDSURFACEDESC desc;
430 HRESULT hr;
432 if (FAILED(IDirect3DDevice2_GetRenderTarget(device, &rt)))
433 return 0;
435 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ds);
436 IDirectDrawSurface_Release(rt);
437 if (FAILED(hr))
438 return 0;
440 desc.dwSize = sizeof(desc);
441 hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
442 IDirectDrawSurface_Release(ds);
443 if (FAILED(hr))
444 return 0;
446 return U2(desc).dwZBufferBitDepth;
449 static IDirectDraw2 *create_ddraw(void)
451 IDirectDraw2 *ddraw2;
452 IDirectDraw *ddraw1;
453 HRESULT hr;
455 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
456 return NULL;
458 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2);
459 IDirectDraw_Release(ddraw1);
460 if (FAILED(hr))
461 return NULL;
463 return ddraw2;
466 static IDirect3DDevice2 *create_device_ex(IDirectDraw2 *ddraw, HWND window, DWORD coop_level, const GUID *device_guid)
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 %#x.\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 %#x.\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 %#x.\n", hr);
501 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
502 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
503 hr = IDirectDrawSurface_SetClipper(surface, clipper);
504 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\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 U2(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 %#x.\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 IDirectDrawSurface_Release(surface);
546 return device;
549 static IDirect3DDevice2 *create_device(IDirectDraw2 *ddraw, HWND window, DWORD coop_level)
551 return create_device_ex(ddraw, window, coop_level, &IID_IDirect3DHALDevice);
554 static IDirect3DViewport2 *create_viewport(IDirect3DDevice2 *device, UINT x, UINT y, UINT w, UINT h)
556 IDirect3DViewport2 *viewport;
557 D3DVIEWPORT2 vp;
558 IDirect3D2 *d3d;
559 HRESULT hr;
561 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
562 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
563 hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
564 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
565 hr = IDirect3DDevice2_AddViewport(device, viewport);
566 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
567 memset(&vp, 0, sizeof(vp));
568 vp.dwSize = sizeof(vp);
569 vp.dwX = x;
570 vp.dwY = y;
571 vp.dwWidth = w;
572 vp.dwHeight = h;
573 vp.dvClipX = -1.0f;
574 vp.dvClipY = 1.0f;
575 vp.dvClipWidth = 2.0f;
576 vp.dvClipHeight = 2.0f;
577 vp.dvMinZ = 0.0f;
578 vp.dvMaxZ = 1.0f;
579 hr = IDirect3DViewport2_SetViewport2(viewport, &vp);
580 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
581 IDirect3D2_Release(d3d);
583 return viewport;
586 static void viewport_set_background(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport,
587 IDirect3DMaterial2 *material)
589 D3DMATERIALHANDLE material_handle;
590 HRESULT hr;
592 hr = IDirect3DMaterial2_GetHandle(material, device, &material_handle);
593 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
594 hr = IDirect3DViewport2_SetBackground(viewport, material_handle);
595 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
598 static void destroy_viewport(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport)
600 HRESULT hr;
602 hr = IDirect3DDevice2_DeleteViewport(device, viewport);
603 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
604 IDirect3DViewport2_Release(viewport);
607 static IDirect3DMaterial2 *create_material(IDirect3DDevice2 *device, D3DMATERIAL *mat)
609 IDirect3DMaterial2 *material;
610 IDirect3D2 *d3d;
611 HRESULT hr;
613 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
614 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
615 hr = IDirect3D2_CreateMaterial(d3d, &material, NULL);
616 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
617 hr = IDirect3DMaterial2_SetMaterial(material, mat);
618 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
619 IDirect3D2_Release(d3d);
621 return material;
624 static IDirect3DMaterial2 *create_diffuse_material(IDirect3DDevice2 *device, float r, float g, float b, float a)
626 D3DMATERIAL mat;
628 memset(&mat, 0, sizeof(mat));
629 mat.dwSize = sizeof(mat);
630 U1(U(mat).diffuse).r = r;
631 U2(U(mat).diffuse).g = g;
632 U3(U(mat).diffuse).b = b;
633 U4(U(mat).diffuse).a = a;
635 return create_material(device, &mat);
638 static IDirect3DMaterial2 *create_diffuse_and_ambient_material(IDirect3DDevice2 *device,
639 float r, float g, float b, float a)
641 D3DMATERIAL mat;
643 memset(&mat, 0, sizeof(mat));
644 mat.dwSize = sizeof(mat);
645 U1(U(mat).diffuse).r = r;
646 U2(U(mat).diffuse).g = g;
647 U3(U(mat).diffuse).b = b;
648 U4(U(mat).diffuse).a = a;
650 U1(U(mat).ambient).r = r;
651 U2(U(mat).ambient).g = g;
652 U3(U(mat).ambient).b = b;
653 U4(U(mat).ambient).a = a;
655 return create_material(device, &mat);
658 static IDirect3DMaterial2 *create_specular_material(IDirect3DDevice2 *device,
659 float r, float g, float b, float a, float power)
661 D3DMATERIAL mat;
663 memset(&mat, 0, sizeof(mat));
664 mat.dwSize = sizeof(mat);
665 U1(U2(mat).specular).r = r;
666 U2(U2(mat).specular).g = g;
667 U3(U2(mat).specular).b = b;
668 U4(U2(mat).specular).a = a;
669 U4(mat).power = power;
671 return create_material(device, &mat);
674 static IDirect3DMaterial2 *create_emissive_material(IDirect3DDevice2 *device, float r, float g, float b, float a)
676 D3DMATERIAL mat;
678 memset(&mat, 0, sizeof(mat));
679 mat.dwSize = sizeof(mat);
680 U1(U3(mat).emissive).r = r;
681 U2(U3(mat).emissive).g = g;
682 U3(U3(mat).emissive).b = b;
683 U4(U3(mat).emissive).a = a;
685 return create_material(device, &mat);
688 static void destroy_material(IDirect3DMaterial2 *material)
690 IDirect3DMaterial2_Release(material);
693 struct message
695 UINT message;
696 BOOL check_wparam;
697 WPARAM expect_wparam;
700 static const struct message *expect_messages;
702 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
704 if (expect_messages && message == expect_messages->message)
706 if (expect_messages->check_wparam)
707 ok (wparam == expect_messages->expect_wparam,
708 "Got unexpected wparam %lx for message %x, expected %lx.\n",
709 wparam, message, expect_messages->expect_wparam);
711 ++expect_messages;
714 return DefWindowProcA(hwnd, message, wparam, lparam);
717 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
718 * interface. This prevents subsequent SetCooperativeLevel() calls on a
719 * different window from failing with DDERR_HWNDALREADYSET. */
720 static void fix_wndproc(HWND window, LONG_PTR proc)
722 IDirectDraw2 *ddraw;
723 HRESULT hr;
725 if (!(ddraw = create_ddraw()))
726 return;
728 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
729 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
730 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
731 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
732 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
734 IDirectDraw2_Release(ddraw);
737 static HRESULT CALLBACK restore_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
739 HRESULT hr = IDirectDrawSurface_Restore(surface);
740 ok(SUCCEEDED(hr) || hr == DDERR_IMPLICITLYCREATED, "Failed to restore surface, hr %#x.\n", hr);
741 IDirectDrawSurface_Release(surface);
743 return DDENUMRET_OK;
746 static HRESULT restore_surfaces(IDirectDraw2 *ddraw)
748 return IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
749 NULL, NULL, restore_callback);
752 static void test_coop_level_create_device_window(void)
754 HWND focus_window, device_window;
755 IDirectDraw2 *ddraw;
756 HRESULT hr;
758 focus_window = create_window();
759 ddraw = create_ddraw();
760 ok(!!ddraw, "Failed to create a ddraw object.\n");
762 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
763 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
764 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
765 ok(!device_window, "Unexpected device window found.\n");
766 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
767 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\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 | DDSCL_NORMAL);
771 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\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 | DDSCL_FULLSCREEN);
775 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\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_EXCLUSIVE | DDSCL_FULLSCREEN);
779 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
780 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
781 ok(!device_window, "Unexpected device window found.\n");
783 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
784 if (broken(hr == DDERR_INVALIDPARAMS))
786 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
787 IDirectDraw2_Release(ddraw);
788 DestroyWindow(focus_window);
789 return;
792 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
793 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
794 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
795 ok(!device_window, "Unexpected device window found.\n");
796 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
797 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
798 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
799 ok(!device_window, "Unexpected device window found.\n");
801 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
802 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
803 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
804 ok(!device_window, "Unexpected device window found.\n");
805 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
806 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
807 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
808 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
809 ok(!!device_window, "Device window not found.\n");
811 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
812 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
813 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
814 ok(!device_window, "Unexpected device window found.\n");
815 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
816 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
817 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
818 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
819 ok(!!device_window, "Device window not found.\n");
821 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
822 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
823 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
824 ok(!device_window, "Unexpected device window found.\n");
825 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
826 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
827 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
828 ok(!device_window, "Unexpected device window found.\n");
829 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
830 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
831 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
832 ok(!device_window, "Unexpected device window found.\n");
833 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
834 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
835 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
836 ok(!!device_window, "Device window not found.\n");
838 IDirectDraw2_Release(ddraw);
839 DestroyWindow(focus_window);
842 static void test_clipper_blt(void)
844 IDirectDrawSurface *src_surface, *dst_surface;
845 RECT client_rect, src_rect;
846 IDirectDrawClipper *clipper;
847 DDSURFACEDESC surface_desc;
848 unsigned int i, j, x, y;
849 IDirectDraw2 *ddraw;
850 RGNDATA *rgn_data;
851 D3DCOLOR color;
852 ULONG refcount;
853 HRGN r1, r2;
854 HWND window;
855 DDBLTFX fx;
856 HRESULT hr;
857 DWORD *ptr;
858 DWORD ret;
860 static const DWORD src_data[] =
862 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
863 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
864 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
866 static const D3DCOLOR expected1[] =
868 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
869 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
870 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
871 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
873 /* Nvidia on Windows seems to have an off-by-one error
874 * when processing source rectangles. Our left = 1 and
875 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
876 * read as well, but only for the edge pixels on the
877 * output image. The bug happens on the y axis as well,
878 * but we only read one row there, and all source rows
879 * contain the same data. This bug is not dependent on
880 * the presence of a clipper. */
881 static const D3DCOLOR expected1_broken[] =
883 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
884 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
885 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
886 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
888 static const D3DCOLOR expected2[] =
890 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
891 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
892 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
893 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
896 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
897 10, 10, 640, 480, 0, 0, 0, 0);
898 ShowWindow(window, SW_SHOW);
899 ddraw = create_ddraw();
900 ok(!!ddraw, "Failed to create a ddraw object.\n");
902 ret = GetClientRect(window, &client_rect);
903 ok(ret, "Failed to get client rect.\n");
904 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
905 ok(ret, "Failed to map client rect.\n");
907 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
908 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
910 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
911 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
912 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
913 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
914 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
915 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
916 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
917 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
918 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
919 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
920 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
921 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
922 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
923 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
924 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
925 "Got unexpected bounding rect %s, expected %s.\n",
926 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
927 HeapFree(GetProcessHeap(), 0, rgn_data);
929 r1 = CreateRectRgn(0, 0, 320, 240);
930 ok(!!r1, "Failed to create region.\n");
931 r2 = CreateRectRgn(320, 240, 640, 480);
932 ok(!!r2, "Failed to create region.\n");
933 CombineRgn(r1, r1, r2, RGN_OR);
934 ret = GetRegionData(r1, 0, NULL);
935 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
936 ret = GetRegionData(r1, ret, rgn_data);
937 ok(!!ret, "Failed to get region data.\n");
939 DeleteObject(r2);
940 DeleteObject(r1);
942 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
943 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
944 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
945 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
946 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
947 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
949 HeapFree(GetProcessHeap(), 0, rgn_data);
951 memset(&surface_desc, 0, sizeof(surface_desc));
952 surface_desc.dwSize = sizeof(surface_desc);
953 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
954 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
955 surface_desc.dwWidth = 640;
956 surface_desc.dwHeight = 480;
957 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
958 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
959 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
960 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
961 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
962 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
964 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
965 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
966 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
967 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
969 memset(&fx, 0, sizeof(fx));
970 fx.dwSize = sizeof(fx);
971 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
972 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
973 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
974 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
976 hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
977 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
978 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
979 ptr = surface_desc.lpSurface;
980 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
981 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
982 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
983 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
984 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
986 hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
987 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
989 SetRect(&src_rect, 1, 1, 5, 2);
990 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
991 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
992 for (i = 0; i < 4; ++i)
994 for (j = 0; j < 4; ++j)
996 x = 80 * ((2 * j) + 1);
997 y = 60 * ((2 * i) + 1);
998 color = get_surface_color(dst_surface, x, y);
999 ok(compare_color(color, expected1[i * 4 + j], 1)
1000 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
1001 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
1005 U5(fx).dwFillColor = 0xff0000ff;
1006 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1007 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
1008 for (i = 0; i < 4; ++i)
1010 for (j = 0; j < 4; ++j)
1012 x = 80 * ((2 * j) + 1);
1013 y = 60 * ((2 * i) + 1);
1014 color = get_surface_color(dst_surface, x, y);
1015 ok(compare_color(color, expected2[i * 4 + j], 1),
1016 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
1020 hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
1021 ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
1023 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
1024 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
1025 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1026 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
1027 DestroyWindow(window);
1028 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1029 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
1030 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
1031 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
1032 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1033 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
1034 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
1035 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
1036 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1037 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
1038 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1039 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
1041 IDirectDrawSurface_Release(dst_surface);
1042 IDirectDrawSurface_Release(src_surface);
1043 refcount = IDirectDrawClipper_Release(clipper);
1044 ok(!refcount, "Clipper has %u references left.\n", refcount);
1045 IDirectDraw2_Release(ddraw);
1048 static void test_coop_level_d3d_state(void)
1050 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1051 IDirectDrawSurface *rt, *surface;
1052 IDirect3DMaterial2 *background;
1053 IDirect3DViewport2 *viewport;
1054 IDirect3DDevice2 *device;
1055 D3DMATERIAL material;
1056 IDirectDraw2 *ddraw;
1057 DDSURFACEDESC lock;
1058 D3DCOLOR color;
1059 DWORD value;
1060 HWND window;
1061 HRESULT hr;
1063 static D3DLVERTEX quad[] =
1065 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0x800000ff}},
1066 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0x800000ff}},
1067 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0x800000ff}},
1068 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0x800000ff}},
1071 window = create_window();
1072 ddraw = create_ddraw();
1073 ok(!!ddraw, "Failed to create a ddraw object.\n");
1074 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1076 skip("Failed to create a 3D device, skipping test.\n");
1077 IDirectDraw2_Release(ddraw);
1078 DestroyWindow(window);
1079 return;
1082 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1083 viewport = create_viewport(device, 0, 0, 640, 480);
1084 viewport_set_background(device, viewport, background);
1086 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1087 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1088 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
1089 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1091 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1092 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1093 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1094 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1095 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1096 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1097 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1098 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
1099 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
1100 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1101 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1102 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1103 color = get_surface_color(rt, 320, 240);
1104 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1106 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1107 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1108 hr = IDirectDrawSurface_IsLost(rt);
1109 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1111 memset(&lock, 0, sizeof(lock));
1112 lock.dwSize = sizeof(lock);
1113 lock.lpSurface = (void *)0xdeadbeef;
1114 hr = IDirectDrawSurface2_Lock(rt, NULL, &lock, DDLOCK_READONLY, NULL);
1115 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1116 ok(lock.lpSurface == (void *)0xdeadbeef, "Got unexpected lock.lpSurface %p.\n", lock.lpSurface);
1118 hr = restore_surfaces(ddraw);
1119 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1121 hr = IDirectDrawSurface2_Lock(rt, NULL, &lock, DDLOCK_READONLY, NULL);
1122 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1123 hr = IDirectDrawSurface2_Unlock(rt, NULL);
1124 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1126 memset(&material, 0, sizeof(material));
1127 material.dwSize = sizeof(material);
1128 U1(U(material).diffuse).r = 0.0f;
1129 U2(U(material).diffuse).g = 1.0f;
1130 U3(U(material).diffuse).b = 0.0f;
1131 U4(U(material).diffuse).a = 1.0f;
1132 hr = IDirect3DMaterial2_SetMaterial(background, &material);
1133 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1135 hr = IDirect3DDevice2_GetRenderTarget(device, &surface);
1136 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1137 ok(surface == rt, "Got unexpected surface %p.\n", surface);
1138 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1139 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1140 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1141 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1142 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1143 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
1144 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1145 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1146 color = get_surface_color(rt, 320, 240);
1147 ok(compare_color(color, 0x0000ff00, 1) || broken(compare_color(color, 0x00000000, 1)),
1148 "Got unexpected color 0x%08x.\n", color);
1150 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1151 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1152 hr = IDirect3DDevice2_BeginScene(device);
1153 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1154 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, ARRAY_SIZE(quad), 0);
1155 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1156 hr = IDirect3DDevice2_EndScene(device);
1157 ok(hr == DD_OK || broken(ddraw_is_warp(ddraw) && hr == DDERR_SURFACELOST), "Got unexpected hr %#x.\n", hr);
1158 if (hr == DD_OK)
1160 color = get_surface_color(rt, 320, 240);
1161 ok(compare_color(color, 0x0000ff80, 1), "Got unexpected color 0x%08x.\n", color);
1164 destroy_viewport(device, viewport);
1165 destroy_material(background);
1166 IDirectDrawSurface_Release(surface);
1167 IDirectDrawSurface_Release(rt);
1168 IDirect3DDevice2_Release(device);
1169 IDirectDraw2_Release(ddraw);
1170 DestroyWindow(window);
1173 static void test_surface_interface_mismatch(void)
1175 IDirectDraw2 *ddraw = NULL;
1176 IDirect3D2 *d3d = NULL;
1177 IDirectDrawSurface *surface = NULL, *ds;
1178 IDirectDrawSurface3 *surface3 = NULL;
1179 IDirect3DDevice2 *device = NULL;
1180 IDirect3DViewport2 *viewport = NULL;
1181 IDirect3DMaterial2 *background = NULL;
1182 DDSURFACEDESC surface_desc;
1183 DWORD z_depth = 0;
1184 ULONG refcount;
1185 HRESULT hr;
1186 D3DCOLOR color;
1187 HWND window;
1188 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1190 window = create_window();
1191 ddraw = create_ddraw();
1192 ok(!!ddraw, "Failed to create a ddraw object.\n");
1193 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1195 skip("Failed to create a 3D device, skipping test.\n");
1196 IDirectDraw2_Release(ddraw);
1197 DestroyWindow(window);
1198 return;
1200 z_depth = get_device_z_depth(device);
1201 ok(!!z_depth, "Failed to get device z depth.\n");
1202 IDirect3DDevice2_Release(device);
1203 device = NULL;
1205 memset(&surface_desc, 0, sizeof(surface_desc));
1206 surface_desc.dwSize = sizeof(surface_desc);
1207 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1208 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1209 surface_desc.dwWidth = 640;
1210 surface_desc.dwHeight = 480;
1212 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1213 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1215 hr = IDirectDrawSurface2_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1216 if (FAILED(hr))
1218 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
1219 goto cleanup;
1222 if (FAILED(IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
1224 skip("D3D interface is not available, skipping test.\n");
1225 goto cleanup;
1228 memset(&surface_desc, 0, sizeof(surface_desc));
1229 surface_desc.dwSize = sizeof(surface_desc);
1230 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
1231 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1232 U2(surface_desc).dwZBufferBitDepth = z_depth;
1233 surface_desc.dwWidth = 640;
1234 surface_desc.dwHeight = 480;
1235 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1236 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
1237 if (FAILED(hr))
1238 goto cleanup;
1240 /* Using a different surface interface version still works */
1241 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1242 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1243 refcount = IDirectDrawSurface_Release(ds);
1244 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1245 if (FAILED(hr))
1246 goto cleanup;
1248 /* Here too */
1249 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface *)surface3, &device);
1250 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1251 if (FAILED(hr))
1252 goto cleanup;
1254 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1255 viewport = create_viewport(device, 0, 0, 640, 480);
1256 viewport_set_background(device, viewport, background);
1258 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1259 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1260 color = get_surface_color(surface, 320, 240);
1261 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1263 cleanup:
1264 if (viewport)
1265 destroy_viewport(device, viewport);
1266 if (background)
1267 destroy_material(background);
1268 if (surface3) IDirectDrawSurface3_Release(surface3);
1269 if (surface) IDirectDrawSurface_Release(surface);
1270 if (device) IDirect3DDevice2_Release(device);
1271 if (d3d) IDirect3D2_Release(d3d);
1272 if (ddraw) IDirectDraw2_Release(ddraw);
1273 DestroyWindow(window);
1276 static void test_coop_level_threaded(void)
1278 struct create_window_thread_param p;
1279 IDirectDraw2 *ddraw;
1280 HRESULT hr;
1282 ddraw = create_ddraw();
1283 ok(!!ddraw, "Failed to create a ddraw object.\n");
1284 create_window_thread(&p);
1286 hr = IDirectDraw2_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1287 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1289 destroy_window_thread(&p);
1290 IDirectDraw2_Release(ddraw);
1293 static void test_depth_blit(const GUID *device_guid)
1295 static D3DLVERTEX quad1[] =
1297 {{-1.0}, { 1.0}, {0.50f}, 0, {0xff00ff00}},
1298 {{ 1.0}, { 1.0}, {0.50f}, 0, {0xff00ff00}},
1299 {{-1.0}, {-1.0}, {0.50f}, 0, {0xff00ff00}},
1300 {{ 1.0}, {-1.0}, {0.50f}, 0, {0xff00ff00}},
1302 static const D3DCOLOR expected_colors[4][4] =
1304 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1305 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1306 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1307 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1309 DDSURFACEDESC ddsd_new, ddsd_existing;
1311 IDirect3DDevice2 *device;
1312 IDirectDrawSurface *ds1, *ds2, *ds3, *rt;
1313 BOOL depth_fill_broken = FALSE;
1314 IDirect3DViewport2 *viewport;
1315 RECT src_rect, dst_rect;
1316 unsigned int i, j;
1317 D3DCOLOR color;
1318 HRESULT hr;
1319 IDirectDraw2 *ddraw;
1320 DDBLTFX fx;
1321 HWND window;
1322 D3DRECT d3drect;
1323 IDirect3DMaterial2 *background;
1325 window = create_window();
1326 ddraw = create_ddraw();
1327 ok(!!ddraw, "Failed to create a ddraw object.\n");
1328 if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid)))
1330 skip("Failed to create a 3D device, skipping test.\n");
1331 IDirectDraw2_Release(ddraw);
1332 DestroyWindow(window);
1333 return;
1336 ds1 = get_depth_stencil(device);
1338 memset(&ddsd_new, 0, sizeof(ddsd_new));
1339 ddsd_new.dwSize = sizeof(ddsd_new);
1340 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1341 ddsd_existing.dwSize = sizeof(ddsd_existing);
1342 hr = IDirectDrawSurface_GetSurfaceDesc(ds1, &ddsd_existing);
1343 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1344 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1345 if (is_software_device_type(device_guid))
1346 ddsd_new.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
1347 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1348 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1349 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1350 ddsd_new.ddpfPixelFormat = ddsd_existing.ddpfPixelFormat;
1351 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1352 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1353 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1354 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1356 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1357 viewport = create_viewport(device, 0, 0, ddsd_existing.dwWidth, ddsd_existing.dwHeight);
1358 viewport_set_background(device, viewport, background);
1359 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1360 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
1362 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1363 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1364 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1365 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1367 U1(d3drect).x1 = U2(d3drect).y1 = 0;
1368 U3(d3drect).x2 = ddsd_existing.dwWidth; U4(d3drect).y2 = ddsd_existing.dwHeight;
1369 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER);
1370 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1372 /* Partial blit. */
1373 SetRect(&src_rect, 0, 0, 320, 240);
1374 SetRect(&dst_rect, 0, 0, 320, 240);
1375 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1376 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1377 /* Different locations. */
1378 SetRect(&src_rect, 0, 0, 320, 240);
1379 SetRect(&dst_rect, 320, 240, 640, 480);
1380 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1381 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1382 /* Stretched. */
1383 SetRect(&src_rect, 0, 0, 320, 240);
1384 SetRect(&dst_rect, 0, 0, 640, 480);
1385 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1386 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1387 /* Flipped. */
1388 SetRect(&src_rect, 0, 480, 640, 0);
1389 SetRect(&dst_rect, 0, 0, 640, 480);
1390 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1391 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1392 SetRect(&src_rect, 0, 0, 640, 480);
1393 SetRect(&dst_rect, 0, 480, 640, 0);
1394 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1395 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1396 /* Full, explicit. */
1397 SetRect(&src_rect, 0, 0, 640, 480);
1398 SetRect(&dst_rect, 0, 0, 640, 480);
1399 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1400 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1401 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1403 /* Depth blit inside a BeginScene / EndScene pair */
1404 hr = IDirect3DDevice2_BeginScene(device);
1405 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1406 /* From the current depth stencil */
1407 hr = IDirectDrawSurface_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1408 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1409 /* To the current depth stencil */
1410 hr = IDirectDrawSurface_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1411 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1412 /* Between unbound surfaces */
1413 hr = IDirectDrawSurface_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1414 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1415 hr = IDirect3DDevice2_EndScene(device);
1416 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1418 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1419 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1420 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1421 * a reliable result(z = 0.0) */
1422 memset(&fx, 0, sizeof(fx));
1423 fx.dwSize = sizeof(fx);
1424 U5(fx).dwFillDepth = 0;
1425 hr = IDirectDrawSurface_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1426 ok(hr == D3D_OK || broken(is_software_device_type(device_guid)
1427 && hr == 0x8876086c /* D3DERR_INVALIDCALL */), "Got unexpected hr %#x.\n", hr);
1428 if (hr != D3D_OK)
1429 depth_fill_broken = TRUE;
1431 /* This clears the Z buffer with 1.0 */
1432 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET);
1433 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1435 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1436 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1438 color = get_surface_color(rt, 80, 60);
1439 /* For some reason clears and colour fill blits randomly fail with software render target. */
1440 ok(color == 0x00ff0000 || broken(is_software_device_type(device_guid) && !color),
1441 "Got unexpected colour 0x%08x.\n", color);
1442 if (!color)
1444 fill_surface(rt, 0xffff0000);
1446 color = get_surface_color(rt, 80, 60);
1447 ok(color == 0x00ff0000, "Got unexpected colour 0x%08x.\n", color);
1450 SetRect(&dst_rect, 0, 0, 320, 240);
1451 hr = IDirectDrawSurface_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1452 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1453 IDirectDrawSurface_Release(ds3);
1454 IDirectDrawSurface_Release(ds2);
1455 IDirectDrawSurface_Release(ds1);
1457 hr = IDirect3DDevice2_BeginScene(device);
1458 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1459 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad1, 4, 0);
1460 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1461 hr = IDirect3DDevice2_EndScene(device);
1462 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1464 for (i = 0; i < 4; ++i)
1466 for (j = 0; j < 4; ++j)
1468 unsigned int x = 80 * ((2 * j) + 1);
1469 unsigned int y = 60 * ((2 * i) + 1);
1470 color = get_surface_color(rt, x, y);
1471 ok(compare_color(color, expected_colors[i][j], 1) || broken(depth_fill_broken && color == 0x0000ff00),
1472 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1475 IDirectDrawSurface_Release(rt);
1477 destroy_viewport(device, viewport);
1478 destroy_material(background);
1479 IDirect3DDevice2_Release(device);
1480 IDirectDraw2_Release(ddraw);
1481 DestroyWindow(window);
1484 static void test_texture_load_ckey(void)
1486 IDirectDraw2 *ddraw = NULL;
1487 IDirectDrawSurface *src = NULL;
1488 IDirectDrawSurface *dst = NULL;
1489 IDirect3DTexture *src_tex = NULL;
1490 IDirect3DTexture *dst_tex = NULL;
1491 DDSURFACEDESC ddsd;
1492 HRESULT hr;
1493 DDCOLORKEY ckey;
1495 ddraw = create_ddraw();
1496 ok(!!ddraw, "Failed to create a ddraw object.\n");
1497 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1498 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1500 memset(&ddsd, 0, sizeof(ddsd));
1501 ddsd.dwSize = sizeof(ddsd);
1502 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1503 ddsd.dwHeight = 128;
1504 ddsd.dwWidth = 128;
1505 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1506 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &src, NULL);
1507 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1508 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1509 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &dst, NULL);
1510 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1512 hr = IDirectDrawSurface_QueryInterface(src, &IID_IDirect3DTexture, (void **)&src_tex);
1513 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1514 if (FAILED(hr))
1516 /* 64 bit ddraw does not support d3d */
1517 skip("Could not get Direct3DTexture interface, skipping texture::Load color keying tests.\n");
1518 goto done;
1520 hr = IDirectDrawSurface_QueryInterface(dst, &IID_IDirect3DTexture, (void **)&dst_tex);
1521 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1523 /* No surface has a color key */
1524 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1525 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDCAPS), "Got unexpected hr %#x.\n", hr);
1526 if (FAILED(hr))
1528 /* Testbot Windows NT VMs */
1529 skip("IDirect3DTexture::Load does not work, skipping color keying tests.\n");
1530 goto done;
1533 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1534 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1535 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1536 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1537 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1539 /* Source surface has a color key */
1540 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1541 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1542 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1543 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1544 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1545 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1546 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1547 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1548 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1550 /* Both surfaces have a color key: Dest ckey is overwritten */
1551 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1552 hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1553 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1554 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1555 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1556 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1557 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1558 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1559 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1561 /* Only the destination has a color key: It is not deleted */
1562 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1563 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1564 hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1565 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1566 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1567 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1568 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1569 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1570 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1571 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1573 done:
1574 if (dst_tex) IDirect3DTexture_Release(dst_tex);
1575 if (src_tex) IDirect3DTexture_Release(src_tex);
1576 if (dst) IDirectDrawSurface_Release(dst);
1577 if (src) IDirectDrawSurface_Release(src);
1578 if (ddraw) IDirectDraw2_Release(ddraw);
1581 static BOOL compare_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
1583 return mode1->dmPosition.x == mode2->dmPosition.x
1584 && mode1->dmPosition.y == mode2->dmPosition.y
1585 && mode1->dmPelsWidth == mode2->dmPelsWidth
1586 && mode1->dmPelsHeight == mode2->dmPelsHeight;
1589 static ULONG get_refcount(IUnknown *test_iface)
1591 IUnknown_AddRef(test_iface);
1592 return IUnknown_Release(test_iface);
1595 static void test_viewport_object(void)
1597 IDirectDraw2 *ddraw;
1598 IDirect3D2 *d3d;
1599 HRESULT hr;
1600 ULONG ref, old_d3d_ref;
1601 D3DVIEWPORT vp;
1602 D3DVIEWPORT2 vp2;
1603 IDirect3DViewport *viewport;
1604 IDirect3DViewport2 *viewport2, *another_vp, *test_vp;
1605 IDirect3DViewport3 *viewport3;
1606 IDirectDrawGammaControl *gamma;
1607 IUnknown *unknown;
1608 IDirect3DDevice2 *device;
1609 HWND window;
1610 union
1612 D3DVIEWPORT2 vp2;
1613 D3DVIEWPORT vp1;
1614 BYTE blob[1024];
1615 } desc;
1617 window = create_window();
1618 ddraw = create_ddraw();
1619 ok(!!ddraw, "Failed to create a ddraw object.\n");
1620 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1622 skip("Failed to create a 3D device, skipping test.\n");
1623 IDirectDraw2_Release(ddraw);
1624 DestroyWindow(window);
1625 return;
1628 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
1629 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get d3d interface, hr %#x.\n", hr);
1630 if (FAILED(hr))
1632 skip("D3D interface is not available, skipping test.\n");
1633 IDirectDraw2_Release(ddraw);
1634 return;
1636 old_d3d_ref = get_refcount((IUnknown *)d3d);
1638 hr = IDirect3D2_CreateViewport(d3d, &viewport2, NULL);
1639 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1640 ref = get_refcount((IUnknown *)viewport2);
1641 ok(ref == 1, "Got unexpected refcount %u.\n", ref);
1642 ref = get_refcount((IUnknown *)d3d);
1643 ok(ref == old_d3d_ref, "Got unexpected refcount %u.\n", ref);
1645 memset(&desc, 0, sizeof(desc));
1646 hr = IDirect3DViewport2_GetViewport(viewport2, &desc.vp1);
1647 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1648 desc.vp1.dwSize = sizeof(desc.vp1) + 1;
1649 hr = IDirect3DViewport2_GetViewport(viewport2, &desc.vp1);
1650 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1651 desc.vp1.dwSize = sizeof(desc.vp1) - 1;
1652 hr = IDirect3DViewport2_GetViewport(viewport2, &desc.vp1);
1653 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1654 desc.vp1.dwSize = sizeof(desc.vp1);
1655 hr = IDirect3DViewport2_GetViewport(viewport2, &desc.vp1);
1656 ok(hr == D3DERR_VIEWPORTDATANOTSET, "Got unexpected hr %#x.\n", hr);
1657 ok(desc.vp1.dwSize == sizeof(desc.vp1), "Got unexpected dwSize %u.\n", desc.vp1.dwSize);
1658 hr = IDirect3DViewport2_GetViewport2(viewport2, &desc.vp2);
1659 ok(hr == D3DERR_VIEWPORTDATANOTSET, "Got unexpected hr %#x.\n", hr);
1660 ok(desc.vp2.dwSize == sizeof(desc.vp2), "Got unexpected dwSize %u.\n", desc.vp2.dwSize);
1661 desc.vp2.dwSize = sizeof(desc.vp2) + 1;
1662 hr = IDirect3DViewport2_GetViewport2(viewport2, &desc.vp2);
1663 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1665 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1666 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirectDrawGammaControl, (void **)&gamma);
1667 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1668 ok(!gamma, "Interface not set to NULL by failed QI call: %p\n", gamma);
1669 /* NULL iid: Segfaults */
1671 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport, (void **)&viewport);
1672 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1673 ref = get_refcount((IUnknown *)viewport);
1674 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1675 ref = get_refcount((IUnknown *)viewport2);
1676 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1677 IDirect3DViewport_Release(viewport);
1678 viewport = NULL;
1680 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport3, (void **)&viewport3);
1681 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1682 if (viewport3)
1684 ref = get_refcount((IUnknown *)viewport2);
1685 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1686 ref = get_refcount((IUnknown *)viewport3);
1687 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1688 IDirect3DViewport3_Release(viewport3);
1691 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IUnknown, (void **)&unknown);
1692 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1693 ref = get_refcount((IUnknown *)viewport2);
1694 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1695 ref = get_refcount(unknown);
1696 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1697 IUnknown_Release(unknown);
1699 hr = IDirect3DDevice2_DeleteViewport(device, NULL);
1700 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1701 hr = IDirect3DDevice2_GetCurrentViewport(device, NULL);
1702 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1704 hr = IDirect3D2_CreateViewport(d3d, &another_vp, NULL);
1705 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1707 /* Setting a viewport not in the viewport list fails */
1708 hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
1709 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1711 /* AddViewport(NULL): Segfault */
1712 hr = IDirect3DDevice2_AddViewport(device, viewport2);
1713 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1714 ref = get_refcount((IUnknown *) viewport2);
1715 ok(ref == 2, "viewport2 refcount is %u.\n", ref);
1716 hr = IDirect3DDevice2_AddViewport(device, another_vp);
1717 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1718 ref = get_refcount((IUnknown *) another_vp);
1719 ok(ref == 2, "another_vp refcount is %u.\n", ref);
1721 test_vp = (IDirect3DViewport2 *) 0xbaadc0de;
1722 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1723 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1724 ok(test_vp == (IDirect3DViewport2 *) 0xbaadc0de, "Got unexpected pointer %p\n", test_vp);
1726 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
1727 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1728 ref = get_refcount((IUnknown *) viewport2);
1729 ok(ref == 3, "Got unexpected refcount %u.\n", ref);
1730 ref = get_refcount((IUnknown *) device);
1731 ok(ref == 1, "Got unexpected refcount %u.\n", ref);
1733 test_vp = NULL;
1734 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1735 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1736 ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
1737 ref = get_refcount((IUnknown *) viewport2);
1738 ok(ref == 4, "Got unexpected refcount %u.\n", ref);
1739 if (test_vp)
1740 IDirect3DViewport2_Release(test_vp);
1742 /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
1744 /* Cannot set the viewport to NULL */
1745 hr = IDirect3DDevice2_SetCurrentViewport(device, NULL);
1746 ok(hr == DDERR_INVALIDPARAMS, "Failed to set viewport to NULL, hr %#x.\n", hr);
1747 test_vp = NULL;
1748 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1749 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1750 ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
1751 if (test_vp)
1752 IDirect3DViewport2_Release(test_vp);
1754 /* SetCurrentViewport properly releases the old viewport's reference */
1755 hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
1756 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1757 ref = get_refcount((IUnknown *) viewport2);
1758 ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1759 ref = get_refcount((IUnknown *) another_vp);
1760 ok(ref == 3, "Got unexpected refcount %u.\n", ref);
1762 /* Deleting the viewport removes the reference added by AddViewport, but not
1763 * the one added by SetCurrentViewport. */
1764 hr = IDirect3DDevice2_DeleteViewport(device, another_vp);
1765 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1766 ref = get_refcount((IUnknown *) another_vp);
1767 todo_wine ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1769 /* GetCurrentViewport fails though */
1770 test_vp = NULL;
1771 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1772 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1773 ok(!test_vp, "Got unexpected viewport %p\n", test_vp);
1775 /* Setting a different viewport does not free the leaked reference. How
1776 * do I get rid of it? Leak the viewport for now. */
1777 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
1778 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1779 ref = get_refcount((IUnknown *) viewport2);
1780 ok(ref == 3, "Got unexpected refcount %u.\n", ref);
1781 ref = get_refcount((IUnknown *) another_vp);
1782 todo_wine ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1784 memset(&vp, 0, sizeof(vp));
1785 memset(&vp, 0, sizeof(vp2));
1786 vp.dwX = vp2.dwX = 0;
1787 vp.dwY = vp2.dwY = 0;
1788 vp.dwWidth = vp2.dwWidth = 640;
1789 vp.dwHeight = vp2.dwHeight = 480;
1790 vp.dvMinZ = vp2.dvMinZ = 0.0f;
1791 vp.dvMaxZ = vp2.dvMaxZ = 1.0f;
1792 vp.dvScaleX = vp.dwWidth / 2.0f;
1793 vp.dvScaleY = vp.dwHeight / 2.0f;
1794 vp.dvMaxX = 1.0f;
1795 vp.dvMaxY = 1.0f;
1796 vp2.dvClipX = -1.0f;
1797 vp2.dvClipY = 1.0f;
1798 vp2.dvClipWidth = 2.0f;
1799 vp2.dvClipHeight = 2.0f;
1800 hr = IDirect3DViewport2_SetViewport(viewport2, &vp);
1801 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1802 hr = IDirect3DViewport2_SetViewport2(viewport2, &vp2);
1803 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1805 vp.dwSize = sizeof(vp);
1806 hr = IDirect3DViewport2_SetViewport(viewport2, &vp);
1807 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
1808 vp2.dwSize = sizeof(vp2);
1809 hr = IDirect3DViewport2_SetViewport2(viewport2, &vp2);
1810 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
1812 /* Destroying the device removes the viewport, but does not free the reference
1813 * added by SetCurrentViewport. */
1814 IDirect3DDevice2_Release(device);
1815 ref = get_refcount((IUnknown *) viewport2);
1816 todo_wine ok(ref == 2, "Got unexpected refcount %u.\n", ref);
1818 vp.dwSize = sizeof(vp);
1819 hr = IDirect3DViewport2_SetViewport(viewport2, &vp);
1820 ok(hr == D3DERR_VIEWPORTHASNODEVICE, "Got unexpected hr %#x.\n", hr);
1821 vp2.dwSize = sizeof(vp2);
1822 hr = IDirect3DViewport2_SetViewport2(viewport2, &vp2);
1823 ok(hr == D3DERR_VIEWPORTHASNODEVICE, "Got unexpected hr %#x.\n", hr);
1825 IDirect3DViewport2_Release(another_vp);
1826 IDirect3DViewport2_Release(viewport2);
1827 IDirect3D2_Release(d3d);
1828 DestroyWindow(window);
1829 IDirectDraw2_Release(ddraw);
1832 static void test_zenable(void)
1834 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1835 static D3DTLVERTEX tquad[] =
1837 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1838 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1839 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1840 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1842 IDirect3DMaterial2 *background;
1843 IDirect3DViewport2 *viewport;
1844 IDirect3DDevice2 *device;
1845 IDirectDrawSurface *rt;
1846 IDirectDraw2 *ddraw;
1847 D3DCOLOR color;
1848 HWND window;
1849 HRESULT hr;
1850 UINT x, y;
1851 UINT i, j;
1853 window = create_window();
1854 ddraw = create_ddraw();
1855 ok(!!ddraw, "Failed to create a ddraw object.\n");
1856 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1858 skip("Failed to create a 3D device, skipping test.\n");
1859 IDirectDraw2_Release(ddraw);
1860 DestroyWindow(window);
1861 return;
1864 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1865 viewport = create_viewport(device, 0, 0, 640, 480);
1866 viewport_set_background(device, viewport, background);
1867 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1868 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1870 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1871 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1873 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1874 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1875 hr = IDirect3DDevice2_BeginScene(device);
1876 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1877 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, tquad, 4, 0);
1878 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1879 hr = IDirect3DDevice2_EndScene(device);
1880 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1882 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1883 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1884 for (i = 0; i < 4; ++i)
1886 for (j = 0; j < 4; ++j)
1888 x = 80 * ((2 * j) + 1);
1889 y = 60 * ((2 * i) + 1);
1890 color = get_surface_color(rt, x, y);
1891 ok(compare_color(color, 0x0000ff00, 1),
1892 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1895 IDirectDrawSurface_Release(rt);
1897 destroy_viewport(device, viewport);
1898 destroy_material(background);
1899 IDirect3DDevice2_Release(device);
1900 IDirectDraw2_Release(ddraw);
1901 DestroyWindow(window);
1904 static void test_ck_rgba(void)
1906 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1907 static D3DTLVERTEX tquad[] =
1909 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1910 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1911 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1912 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1913 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1914 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1915 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1916 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1918 static const struct
1920 D3DCOLOR fill_color;
1921 BOOL color_key;
1922 BOOL blend;
1923 D3DCOLOR result1, result1_broken;
1924 D3DCOLOR result2, result2_broken;
1926 tests[] =
1928 /* r200 on Windows doesn't check the alpha component when applying the color
1929 * key, so the key matches on every texel. */
1930 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1931 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1932 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1933 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1934 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1935 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1936 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1937 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1940 D3DTEXTUREHANDLE texture_handle;
1941 IDirect3DMaterial2 *background;
1942 IDirectDrawSurface *surface;
1943 IDirect3DViewport2 *viewport;
1944 IDirect3DTexture2 *texture;
1945 DDSURFACEDESC surface_desc;
1946 IDirect3DDevice2 *device;
1947 IDirectDrawSurface *rt;
1948 IDirectDraw2 *ddraw;
1949 D3DCOLOR color;
1950 HWND window;
1951 DDBLTFX fx;
1952 HRESULT hr;
1953 UINT i;
1955 window = create_window();
1956 ddraw = create_ddraw();
1957 ok(!!ddraw, "Failed to create a ddraw object.\n");
1958 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1960 skip("Failed to create a 3D device, skipping test.\n");
1961 IDirectDraw2_Release(ddraw);
1962 DestroyWindow(window);
1963 return;
1966 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1967 viewport = create_viewport(device, 0, 0, 640, 480);
1968 viewport_set_background(device, viewport, background);
1969 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1970 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1972 memset(&surface_desc, 0, sizeof(surface_desc));
1973 surface_desc.dwSize = sizeof(surface_desc);
1974 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1975 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1976 surface_desc.dwWidth = 256;
1977 surface_desc.dwHeight = 256;
1978 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1979 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1980 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1981 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1982 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1983 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1984 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1985 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1986 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1987 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1988 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1989 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1990 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1991 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
1992 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1993 IDirect3DTexture2_Release(texture);
1995 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1996 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1997 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1998 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1999 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
2000 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
2002 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
2003 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
2005 for (i = 0; i < ARRAY_SIZE(tests); ++i)
2007 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
2008 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
2009 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
2010 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
2012 memset(&fx, 0, sizeof(fx));
2013 fx.dwSize = sizeof(fx);
2014 U5(fx).dwFillColor = tests[i].fill_color;
2015 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
2016 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
2018 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
2019 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2020 hr = IDirect3DDevice2_BeginScene(device);
2021 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
2022 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
2023 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
2024 hr = IDirect3DDevice2_EndScene(device);
2025 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
2027 color = get_surface_color(rt, 320, 240);
2028 ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
2029 "Expected color 0x%08x for test %u, got 0x%08x.\n",
2030 tests[i].result1, i, color);
2032 U5(fx).dwFillColor = 0xff0000ff;
2033 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
2034 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
2036 hr = IDirect3DDevice2_BeginScene(device);
2037 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
2038 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[4], 4, 0);
2039 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
2040 hr = IDirect3DDevice2_EndScene(device);
2041 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
2043 /* This tests that fragments that are masked out by the color key are
2044 * discarded, instead of just fully transparent. */
2045 color = get_surface_color(rt, 320, 240);
2046 ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
2047 "Expected color 0x%08x for test %u, got 0x%08x.\n",
2048 tests[i].result2, i, color);
2051 IDirectDrawSurface_Release(rt);
2052 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
2053 ok(SUCCEEDED(hr), "Failed to unset texture, hr %#x.\n", hr);
2054 IDirectDrawSurface_Release(surface);
2055 destroy_viewport(device, viewport);
2056 destroy_material(background);
2057 IDirect3DDevice2_Release(device);
2058 IDirectDraw2_Release(ddraw);
2059 DestroyWindow(window);
2062 static void test_ck_default(void)
2064 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
2065 static D3DTLVERTEX tquad[] =
2067 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
2068 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
2069 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
2070 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
2072 IDirectDrawSurface *surface, *rt;
2073 D3DTEXTUREHANDLE texture_handle;
2074 IDirect3DMaterial2 *background;
2075 IDirect3DViewport2 *viewport;
2076 DDSURFACEDESC surface_desc;
2077 IDirect3DTexture2 *texture;
2078 IDirect3DDevice2 *device;
2079 IDirectDraw2 *ddraw;
2080 D3DCOLOR color;
2081 DWORD value;
2082 HWND window;
2083 DDBLTFX fx;
2084 HRESULT hr;
2086 window = create_window();
2087 ddraw = create_ddraw();
2088 ok(!!ddraw, "Failed to create a ddraw object.\n");
2089 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2091 skip("Failed to create a 3D device, skipping test.\n");
2092 IDirectDraw2_Release(ddraw);
2093 DestroyWindow(window);
2094 return;
2097 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
2098 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
2100 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
2101 viewport = create_viewport(device, 0, 0, 640, 480);
2102 viewport_set_background(device, viewport, background);
2103 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
2104 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
2106 memset(&surface_desc, 0, sizeof(surface_desc));
2107 surface_desc.dwSize = sizeof(surface_desc);
2108 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
2109 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2110 surface_desc.dwWidth = 256;
2111 surface_desc.dwHeight = 256;
2112 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
2113 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
2114 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
2115 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
2116 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
2117 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
2118 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
2119 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
2120 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2121 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2122 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
2123 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
2124 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
2125 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
2126 IDirect3DTexture_Release(texture);
2128 memset(&fx, 0, sizeof(fx));
2129 fx.dwSize = sizeof(fx);
2130 U5(fx).dwFillColor = 0x000000ff;
2131 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
2132 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
2134 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2135 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2136 hr = IDirect3DDevice2_BeginScene(device);
2137 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
2138 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
2139 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
2140 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
2141 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
2142 ok(!value, "Got unexpected color keying state %#x.\n", value);
2143 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
2144 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
2145 hr = IDirect3DDevice2_EndScene(device);
2146 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
2147 color = get_surface_color(rt, 320, 240);
2148 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
2150 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2151 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2152 hr = IDirect3DDevice2_BeginScene(device);
2153 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
2154 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
2155 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
2156 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
2157 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
2158 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
2159 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
2160 ok(!!value, "Got unexpected color keying state %#x.\n", value);
2161 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
2162 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
2163 hr = IDirect3DDevice2_EndScene(device);
2164 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
2165 color = get_surface_color(rt, 320, 240);
2166 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
2168 IDirectDrawSurface_Release(surface);
2169 destroy_viewport(device, viewport);
2170 destroy_material(background);
2171 IDirectDrawSurface_Release(rt);
2172 IDirect3DDevice2_Release(device);
2173 IDirectDraw2_Release(ddraw);
2174 DestroyWindow(window);
2177 static void test_ck_complex(void)
2179 IDirectDrawSurface *surface, *mipmap, *tmp;
2180 DDSCAPS caps = {DDSCAPS_COMPLEX};
2181 DDSURFACEDESC surface_desc;
2182 IDirect3DDevice2 *device;
2183 DDCOLORKEY color_key;
2184 IDirectDraw2 *ddraw;
2185 unsigned int i;
2186 ULONG refcount;
2187 HWND window;
2188 HRESULT hr;
2190 window = create_window();
2191 ddraw = create_ddraw();
2192 ok(!!ddraw, "Failed to create a ddraw object.\n");
2193 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
2195 skip("Failed to create a 3D device, skipping test.\n");
2196 DestroyWindow(window);
2197 IDirectDraw2_Release(ddraw);
2198 return;
2200 IDirect3DDevice2_Release(device);
2202 memset(&surface_desc, 0, sizeof(surface_desc));
2203 surface_desc.dwSize = sizeof(surface_desc);
2204 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2205 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2206 surface_desc.dwWidth = 128;
2207 surface_desc.dwHeight = 128;
2208 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2209 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2211 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2212 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
2213 color_key.dwColorSpaceLowValue = 0x0000ff00;
2214 color_key.dwColorSpaceHighValue = 0x0000ff00;
2215 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2216 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2217 memset(&color_key, 0, sizeof(color_key));
2218 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2219 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2220 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2221 color_key.dwColorSpaceLowValue);
2222 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2223 color_key.dwColorSpaceHighValue);
2225 mipmap = surface;
2226 IDirectDrawSurface_AddRef(mipmap);
2227 for (i = 0; i < 7; ++i)
2229 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
2230 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
2232 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2233 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2234 color_key.dwColorSpaceLowValue = 0x000000ff;
2235 color_key.dwColorSpaceHighValue = 0x000000ff;
2236 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2237 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x, i %u.\n", hr, i);
2238 memset(&color_key, 0, sizeof(color_key));
2239 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2240 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x, i %u.\n", hr, i);
2241 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
2242 color_key.dwColorSpaceLowValue, i);
2243 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
2244 color_key.dwColorSpaceHighValue, i);
2246 IDirectDrawSurface_Release(mipmap);
2247 mipmap = tmp;
2250 memset(&color_key, 0, sizeof(color_key));
2251 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2252 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2253 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2254 color_key.dwColorSpaceLowValue);
2255 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2256 color_key.dwColorSpaceHighValue);
2258 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
2259 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
2260 IDirectDrawSurface_Release(mipmap);
2261 refcount = IDirectDrawSurface_Release(surface);
2262 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2264 memset(&surface_desc, 0, sizeof(surface_desc));
2265 surface_desc.dwSize = sizeof(surface_desc);
2266 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
2267 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
2268 surface_desc.dwBackBufferCount = 1;
2269 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2270 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2272 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2273 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
2274 color_key.dwColorSpaceLowValue = 0x0000ff00;
2275 color_key.dwColorSpaceHighValue = 0x0000ff00;
2276 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2277 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2278 memset(&color_key, 0, sizeof(color_key));
2279 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2280 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2281 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2282 color_key.dwColorSpaceLowValue);
2283 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2284 color_key.dwColorSpaceHighValue);
2286 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
2287 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
2289 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2290 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2291 color_key.dwColorSpaceLowValue = 0x0000ff00;
2292 color_key.dwColorSpaceHighValue = 0x0000ff00;
2293 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2294 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2295 memset(&color_key, 0, sizeof(color_key));
2296 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2297 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2298 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2299 color_key.dwColorSpaceLowValue);
2300 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2301 color_key.dwColorSpaceHighValue);
2303 IDirectDrawSurface_Release(tmp);
2305 refcount = IDirectDrawSurface_Release(surface);
2306 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2307 refcount = IDirectDraw2_Release(ddraw);
2308 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2309 DestroyWindow(window);
2312 struct qi_test
2314 REFIID iid;
2315 REFIID refcount_iid;
2316 HRESULT hr;
2319 static void test_qi(const char *test_name, IUnknown *base_iface,
2320 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
2322 ULONG refcount, expected_refcount;
2323 IUnknown *iface1, *iface2;
2324 HRESULT hr;
2325 UINT i, j;
2327 for (i = 0; i < entry_count; ++i)
2329 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
2330 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
2331 if (SUCCEEDED(hr))
2333 for (j = 0; j < entry_count; ++j)
2335 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
2336 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
2337 if (SUCCEEDED(hr))
2339 expected_refcount = 0;
2340 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
2341 ++expected_refcount;
2342 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
2343 ++expected_refcount;
2344 refcount = IUnknown_Release(iface2);
2345 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
2346 refcount, test_name, i, j, expected_refcount);
2350 expected_refcount = 0;
2351 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
2352 ++expected_refcount;
2353 refcount = IUnknown_Release(iface1);
2354 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
2355 refcount, test_name, i, expected_refcount);
2360 static void test_surface_qi(void)
2362 static const struct qi_test tests[] =
2364 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
2365 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
2366 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
2367 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2368 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
2369 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
2370 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
2371 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
2372 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
2373 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
2374 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
2375 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
2376 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
2377 {&IID_IDirect3D7, NULL, E_INVALIDARG },
2378 {&IID_IDirect3D3, NULL, E_INVALIDARG },
2379 {&IID_IDirect3D2, NULL, E_INVALIDARG },
2380 {&IID_IDirect3D, NULL, E_INVALIDARG },
2381 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
2382 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
2383 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
2384 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
2385 {&IID_IDirectDraw, NULL, E_INVALIDARG },
2386 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
2387 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
2388 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
2389 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
2390 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
2391 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
2392 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
2393 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
2394 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
2395 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
2396 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
2397 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
2398 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
2399 {NULL, NULL, E_INVALIDARG },
2402 IDirectDrawSurface *surface;
2403 DDSURFACEDESC surface_desc;
2404 IDirect3DDevice2 *device;
2405 IDirectDraw2 *ddraw;
2406 HWND window;
2407 HRESULT hr;
2409 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
2411 win_skip("DirectDrawCreateEx not available, skipping test.\n");
2412 return;
2415 window = create_window();
2416 ddraw = create_ddraw();
2417 ok(!!ddraw, "Failed to create a ddraw object.\n");
2418 /* Try to create a D3D device to see if the ddraw implementation supports
2419 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
2420 * doesn't support e.g. the IDirect3DTexture interfaces. */
2421 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2423 skip("Failed to create a 3D device, skipping test.\n");
2424 IDirectDraw2_Release(ddraw);
2425 DestroyWindow(window);
2426 return;
2428 IDirect3DDevice_Release(device);
2430 memset(&surface_desc, 0, sizeof(surface_desc));
2431 surface_desc.dwSize = sizeof(surface_desc);
2432 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2433 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2434 surface_desc.dwWidth = 512;
2435 surface_desc.dwHeight = 512;
2436 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, (IDirectDrawSurface **)0xdeadbeef, NULL);
2437 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2438 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2439 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2441 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, ARRAY_SIZE(tests));
2443 IDirectDrawSurface_Release(surface);
2444 IDirectDraw2_Release(ddraw);
2445 DestroyWindow(window);
2448 static void test_device_qi(void)
2450 static const struct qi_test tests[] =
2452 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2453 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2454 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2455 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2456 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2457 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2458 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2459 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2460 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2461 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
2462 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
2463 {&IID_IDirect3DDevice2, &IID_IDirect3DDevice2, S_OK },
2464 {&IID_IDirect3DDevice, &IID_IDirect3DDevice2, S_OK },
2465 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2466 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2467 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2468 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2469 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2470 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2471 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2472 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2473 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2474 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2475 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2476 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2477 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2478 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2479 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2480 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2481 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2482 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2483 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2484 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2485 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2486 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2487 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2488 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2489 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2490 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2491 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2492 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2493 {&IID_IUnknown, &IID_IDirect3DDevice2, S_OK },
2496 IDirect3DDevice2 *device;
2497 IDirectDraw2 *ddraw;
2498 HWND window;
2500 window = create_window();
2501 ddraw = create_ddraw();
2502 ok(!!ddraw, "Failed to create a ddraw object.\n");
2503 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2505 skip("Failed to create a 3D device, skipping test.\n");
2506 IDirectDraw2_Release(ddraw);
2507 DestroyWindow(window);
2508 return;
2511 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice2, tests, ARRAY_SIZE(tests));
2513 IDirect3DDevice2_Release(device);
2514 IDirectDraw2_Release(ddraw);
2515 DestroyWindow(window);
2518 static void test_wndproc(void)
2520 LONG_PTR proc, ddraw_proc;
2521 IDirectDraw2 *ddraw;
2522 WNDCLASSA wc = {0};
2523 HWND window;
2524 HRESULT hr;
2525 ULONG ref;
2527 static struct message messages[] =
2529 {WM_WINDOWPOSCHANGING, FALSE, 0},
2530 {WM_MOVE, FALSE, 0},
2531 {WM_SIZE, FALSE, 0},
2532 {WM_WINDOWPOSCHANGING, FALSE, 0},
2533 {WM_ACTIVATE, FALSE, 0},
2534 {WM_SETFOCUS, FALSE, 0},
2535 {0, FALSE, 0},
2538 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2539 ddraw = create_ddraw();
2540 ok(!!ddraw, "Failed to create a ddraw object.\n");
2542 wc.lpfnWndProc = test_proc;
2543 wc.lpszClassName = "ddraw_test_wndproc_wc";
2544 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2546 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2547 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2549 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2550 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2551 (LONG_PTR)test_proc, proc);
2552 expect_messages = messages;
2553 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2554 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2555 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2556 expect_messages = NULL;
2557 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2558 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2559 (LONG_PTR)test_proc, proc);
2560 ref = IDirectDraw2_Release(ddraw);
2561 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2562 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2563 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2564 (LONG_PTR)test_proc, proc);
2566 /* DDSCL_NORMAL doesn't. */
2567 ddraw = create_ddraw();
2568 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2569 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2570 (LONG_PTR)test_proc, proc);
2571 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2572 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2573 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2574 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2575 (LONG_PTR)test_proc, proc);
2576 ref = IDirectDraw2_Release(ddraw);
2577 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2578 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2579 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2580 (LONG_PTR)test_proc, proc);
2582 /* The original window proc is only restored by ddraw if the current
2583 * window proc matches the one ddraw set. This also affects switching
2584 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2585 ddraw = create_ddraw();
2586 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2587 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2588 (LONG_PTR)test_proc, proc);
2589 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2590 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2591 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2592 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2593 (LONG_PTR)test_proc, proc);
2594 ddraw_proc = proc;
2595 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2596 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2597 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2598 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2599 (LONG_PTR)test_proc, proc);
2600 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2601 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2602 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2603 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2604 (LONG_PTR)test_proc, proc);
2605 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2606 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2607 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2608 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2609 (LONG_PTR)DefWindowProcA, proc);
2610 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2611 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2612 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, ddraw_proc);
2613 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2614 (LONG_PTR)DefWindowProcA, proc);
2615 ref = IDirectDraw2_Release(ddraw);
2616 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2617 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2618 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2619 (LONG_PTR)test_proc, proc);
2621 ddraw = create_ddraw();
2622 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2623 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2624 (LONG_PTR)test_proc, proc);
2625 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2626 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2627 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2628 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2629 (LONG_PTR)test_proc, proc);
2630 ref = IDirectDraw2_Release(ddraw);
2631 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2632 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2633 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2634 (LONG_PTR)DefWindowProcA, proc);
2636 fix_wndproc(window, (LONG_PTR)test_proc);
2637 expect_messages = NULL;
2638 DestroyWindow(window);
2639 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2642 static void test_window_style(void)
2644 LONG style, exstyle, tmp, expected_style;
2645 RECT fullscreen_rect, r;
2646 IDirectDraw2 *ddraw;
2647 HWND window;
2648 HRESULT hr;
2649 ULONG ref;
2650 BOOL ret;
2652 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2653 0, 0, 100, 100, 0, 0, 0, 0);
2654 ddraw = create_ddraw();
2655 ok(!!ddraw, "Failed to create a ddraw object.\n");
2657 style = GetWindowLongA(window, GWL_STYLE);
2658 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2659 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2661 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2662 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2664 tmp = GetWindowLongA(window, GWL_STYLE);
2665 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2666 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2667 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2669 GetWindowRect(window, &r);
2670 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2671 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2672 GetClientRect(window, &r);
2673 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2675 ret = SetForegroundWindow(GetDesktopWindow());
2676 ok(ret, "Failed to set foreground window.\n");
2678 tmp = GetWindowLongA(window, GWL_STYLE);
2679 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2680 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2681 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2683 ret = SetForegroundWindow(window);
2684 ok(ret, "Failed to set foreground window.\n");
2685 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2686 * the next tests expect this. */
2687 ShowWindow(window, SW_HIDE);
2689 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2690 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2692 tmp = GetWindowLongA(window, GWL_STYLE);
2693 ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2694 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2695 ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2697 ShowWindow(window, SW_SHOW);
2698 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2699 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2701 tmp = GetWindowLongA(window, GWL_STYLE);
2702 expected_style = style | WS_VISIBLE;
2703 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2704 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2705 expected_style = exstyle | WS_EX_TOPMOST;
2706 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2708 ret = SetForegroundWindow(GetDesktopWindow());
2709 ok(ret, "Failed to set foreground window.\n");
2710 tmp = GetWindowLongA(window, GWL_STYLE);
2711 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2712 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2713 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2714 expected_style = exstyle | WS_EX_TOPMOST;
2715 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2717 ref = IDirectDraw2_Release(ddraw);
2718 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2720 DestroyWindow(window);
2723 static void test_redundant_mode_set(void)
2725 DDSURFACEDESC surface_desc = {0};
2726 IDirectDraw2 *ddraw;
2727 RECT q, r, s;
2728 HWND window;
2729 HRESULT hr;
2730 ULONG ref;
2732 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2733 0, 0, 100, 100, 0, 0, 0, 0);
2734 ddraw = create_ddraw();
2735 ok(!!ddraw, "Failed to create a ddraw object.\n");
2737 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2738 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2740 surface_desc.dwSize = sizeof(surface_desc);
2741 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
2742 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
2744 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2745 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, 0, 0);
2746 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2748 GetWindowRect(window, &q);
2749 r = q;
2750 r.right /= 2;
2751 r.bottom /= 2;
2752 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2753 GetWindowRect(window, &s);
2754 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2756 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2757 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, 0, 0);
2758 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2760 GetWindowRect(window, &s);
2761 ok(EqualRect(&r, &s) || broken(EqualRect(&q, &s) /* Windows 10 */),
2762 "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2764 ref = IDirectDraw2_Release(ddraw);
2765 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2767 DestroyWindow(window);
2770 static SIZE screen_size, screen_size2;
2772 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2774 if (message == WM_SIZE)
2776 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2777 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2780 return test_proc(hwnd, message, wparam, lparam);
2783 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2785 if (message == WM_SIZE)
2787 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2788 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2791 return test_proc(hwnd, message, wparam, lparam);
2794 struct test_coop_level_mode_set_enum_param
2796 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2799 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC *surface_desc, void *context)
2801 struct test_coop_level_mode_set_enum_param *param = context;
2803 if (U1(surface_desc->ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2804 return DDENUMRET_OK;
2805 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2806 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2807 return DDENUMRET_OK;
2809 if (!param->ddraw_width)
2811 param->ddraw_width = surface_desc->dwWidth;
2812 param->ddraw_height = surface_desc->dwHeight;
2813 return DDENUMRET_OK;
2815 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2816 return DDENUMRET_OK;
2818 param->user32_width = surface_desc->dwWidth;
2819 param->user32_height = surface_desc->dwHeight;
2820 return DDENUMRET_CANCEL;
2823 static void test_coop_level_mode_set(void)
2825 DEVMODEW *original_modes = NULL, devmode, devmode2;
2826 unsigned int display_count = 0;
2827 IDirectDrawSurface *primary;
2828 RECT registry_rect, ddraw_rect, user32_rect, r;
2829 IDirectDraw2 *ddraw;
2830 DDSURFACEDESC ddsd;
2831 WNDCLASSA wc = {0};
2832 HWND window, window2;
2833 HRESULT hr;
2834 ULONG ref;
2835 MSG msg;
2836 struct test_coop_level_mode_set_enum_param param;
2837 BOOL ret;
2838 LONG change_ret;
2840 static const struct message exclusive_messages[] =
2842 {WM_WINDOWPOSCHANGING, FALSE, 0},
2843 {WM_WINDOWPOSCHANGED, FALSE, 0},
2844 {WM_SIZE, FALSE, 0},
2845 {WM_DISPLAYCHANGE, FALSE, 0},
2846 {0, FALSE, 0},
2848 static const struct message exclusive_focus_loss_messages[] =
2850 {WM_ACTIVATE, TRUE, WA_INACTIVE},
2851 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window resize due to mode change. */
2852 {WM_WINDOWPOSCHANGED, FALSE, 0},
2853 {WM_SIZE, TRUE, SIZE_RESTORED}, /* Generated by DefWindowProc. */
2854 {WM_DISPLAYCHANGE, FALSE, 0},
2855 {WM_KILLFOCUS, FALSE, 0},
2856 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window minimized. */
2857 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2858 * SW_MINIMIZED, causing a recursive window activation that does not
2859 * produce the same result in Wine yet. Ignore the difference for now.
2860 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2861 {WM_WINDOWPOSCHANGED, FALSE, 0},
2862 {WM_MOVE, FALSE, 0},
2863 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2864 {WM_ACTIVATEAPP, TRUE, FALSE},
2865 {0, FALSE, 0},
2867 static const struct message exclusive_focus_restore_messages[] =
2869 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2870 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2871 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2872 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2873 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2874 /* Native redundantly sets the window size here. */
2875 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2876 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2877 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2878 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2879 {0, FALSE, 0},
2881 static const struct message sc_restore_messages[] =
2883 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2884 {WM_WINDOWPOSCHANGING, FALSE, 0},
2885 {WM_WINDOWPOSCHANGED, FALSE, 0},
2886 {WM_SIZE, TRUE, SIZE_RESTORED},
2887 {0, FALSE, 0},
2889 static const struct message sc_minimize_messages[] =
2891 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2892 {WM_WINDOWPOSCHANGING, FALSE, 0},
2893 {WM_WINDOWPOSCHANGED, FALSE, 0},
2894 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2895 {0, FALSE, 0},
2897 static const struct message sc_maximize_messages[] =
2899 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2900 {WM_WINDOWPOSCHANGING, FALSE, 0},
2901 {WM_WINDOWPOSCHANGED, FALSE, 0},
2902 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2903 {0, FALSE, 0},
2906 static const struct message normal_messages[] =
2908 {WM_DISPLAYCHANGE, FALSE, 0},
2909 {0, FALSE, 0},
2912 memset(&devmode, 0, sizeof(devmode));
2913 devmode.dmSize = sizeof(devmode);
2914 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2915 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
2916 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
2917 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
2918 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
2919 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
2921 ret = save_display_modes(&original_modes, &display_count);
2922 ok(ret, "Failed to save original display modes.\n");
2924 ddraw = create_ddraw();
2925 ok(!!ddraw, "Failed to create a ddraw object.\n");
2927 memset(&param, 0, sizeof(param));
2928 hr = IDirectDraw2_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2929 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2930 ref = IDirectDraw2_Release(ddraw);
2931 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2933 if (!param.user32_height)
2935 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2936 heap_free(original_modes);
2937 return;
2940 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2941 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2942 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2944 memset(&devmode, 0, sizeof(devmode));
2945 devmode.dmSize = sizeof(devmode);
2946 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2947 devmode.dmPelsWidth = param.user32_width;
2948 devmode.dmPelsHeight = param.user32_height;
2949 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2950 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2952 ddraw = create_ddraw();
2953 ok(!!ddraw, "Failed to create a ddraw object.\n");
2955 wc.lpfnWndProc = mode_set_proc;
2956 wc.lpszClassName = "ddraw_test_wndproc_wc";
2957 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2958 wc.lpfnWndProc = mode_set_proc2;
2959 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2960 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2962 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2963 0, 0, 100, 100, 0, 0, 0, 0);
2964 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2965 0, 0, 100, 100, 0, 0, 0, 0);
2967 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2968 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2970 GetWindowRect(window, &r);
2971 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2972 wine_dbgstr_rect(&r));
2974 memset(&ddsd, 0, sizeof(ddsd));
2975 ddsd.dwSize = sizeof(ddsd);
2976 ddsd.dwFlags = DDSD_CAPS;
2977 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2979 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2980 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2981 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2982 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2983 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2984 param.user32_width, ddsd.dwWidth);
2985 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2986 param.user32_height, ddsd.dwHeight);
2988 GetWindowRect(window, &r);
2989 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2990 wine_dbgstr_rect(&r));
2992 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2993 expect_messages = exclusive_messages;
2994 screen_size.cx = 0;
2995 screen_size.cy = 0;
2997 hr = IDirectDrawSurface_IsLost(primary);
2998 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2999 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3000 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3001 hr = IDirectDrawSurface_IsLost(primary);
3002 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3004 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3005 expect_messages = NULL;
3006 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
3007 "Expected screen size %ux%u, got %ux%u.\n",
3008 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
3010 GetWindowRect(window, &r);
3011 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3012 wine_dbgstr_rect(&r));
3014 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3015 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3016 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
3017 param.user32_width, ddsd.dwWidth);
3018 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
3019 param.user32_height, ddsd.dwHeight);
3020 IDirectDrawSurface_Release(primary);
3022 memset(&ddsd, 0, sizeof(ddsd));
3023 ddsd.dwSize = sizeof(ddsd);
3024 ddsd.dwFlags = DDSD_CAPS;
3025 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3027 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3028 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3029 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3030 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3031 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3032 param.ddraw_width, ddsd.dwWidth);
3033 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3034 param.ddraw_height, ddsd.dwHeight);
3036 GetWindowRect(window, &r);
3037 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3038 wine_dbgstr_rect(&r));
3040 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3041 expect_messages = exclusive_messages;
3042 screen_size.cx = 0;
3043 screen_size.cy = 0;
3045 hr = IDirectDrawSurface_IsLost(primary);
3046 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3047 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3048 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3049 hr = IDirectDrawSurface_IsLost(primary);
3050 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3052 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3053 expect_messages = NULL;
3054 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
3055 "Expected screen size %ux%u, got %ux%u.\n",
3056 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
3058 GetWindowRect(window, &r);
3059 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
3060 wine_dbgstr_rect(&r));
3062 expect_messages = exclusive_focus_loss_messages;
3063 ret = SetForegroundWindow(GetDesktopWindow());
3064 ok(ret, "Failed to set foreground window.\n");
3065 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3066 memset(&devmode, 0, sizeof(devmode));
3067 devmode.dmSize = sizeof(devmode);
3068 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3069 ok(ret, "Failed to get display mode.\n");
3070 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3071 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpected screen size %ux%u.\n",
3072 devmode.dmPelsWidth, devmode.dmPelsHeight);
3074 expect_messages = exclusive_focus_restore_messages;
3075 ShowWindow(window, SW_RESTORE);
3076 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3078 GetWindowRect(window, &r);
3079 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3080 wine_dbgstr_rect(&r));
3081 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3082 ok(ret, "Failed to get display mode.\n");
3083 ok(devmode.dmPelsWidth == param.ddraw_width
3084 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpected screen size %ux%u.\n",
3085 devmode.dmPelsWidth, devmode.dmPelsHeight);
3087 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3088 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3089 /* Normally the primary should be restored here. Unfortunately this causes the
3090 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
3091 * testbot. Another Restore call would presumably avoid the crash, but it also moots
3092 * the point of the GetSurfaceDesc call. */
3094 expect_messages = sc_minimize_messages;
3095 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3096 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3097 expect_messages = NULL;
3099 expect_messages = sc_restore_messages;
3100 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
3101 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3102 expect_messages = NULL;
3104 expect_messages = sc_maximize_messages;
3105 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3106 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3107 expect_messages = NULL;
3109 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3110 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3112 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3113 expect_messages = exclusive_messages;
3114 screen_size.cx = 0;
3115 screen_size.cy = 0;
3117 hr = IDirectDrawSurface_IsLost(primary);
3118 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3119 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3120 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3121 hr = IDirectDrawSurface_IsLost(primary);
3122 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3124 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3125 expect_messages = NULL;
3126 ok(screen_size.cx == registry_mode.dmPelsWidth
3127 && screen_size.cy == registry_mode.dmPelsHeight,
3128 "Expected screen size %ux%u, got %ux%u.\n",
3129 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
3131 GetWindowRect(window, &r);
3132 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3133 wine_dbgstr_rect(&r));
3135 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3136 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3137 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3138 param.ddraw_width, ddsd.dwWidth);
3139 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3140 param.ddraw_height, ddsd.dwHeight);
3141 IDirectDrawSurface_Release(primary);
3143 /* For Wine. */
3144 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3145 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3147 memset(&ddsd, 0, sizeof(ddsd));
3148 ddsd.dwSize = sizeof(ddsd);
3149 ddsd.dwFlags = DDSD_CAPS;
3150 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3152 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3153 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3154 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3155 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3156 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3157 registry_mode.dmPelsWidth, ddsd.dwWidth);
3158 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3159 registry_mode.dmPelsHeight, ddsd.dwHeight);
3161 GetWindowRect(window, &r);
3162 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3163 wine_dbgstr_rect(&r));
3165 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3166 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3168 GetWindowRect(window, &r);
3169 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3170 wine_dbgstr_rect(&r));
3172 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3173 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3174 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3175 registry_mode.dmPelsWidth, ddsd.dwWidth);
3176 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3177 registry_mode.dmPelsHeight, ddsd.dwHeight);
3178 IDirectDrawSurface_Release(primary);
3180 memset(&ddsd, 0, sizeof(ddsd));
3181 ddsd.dwSize = sizeof(ddsd);
3182 ddsd.dwFlags = DDSD_CAPS;
3183 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3185 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3186 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3187 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3188 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3189 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3190 registry_mode.dmPelsWidth, ddsd.dwWidth);
3191 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3192 registry_mode.dmPelsHeight, ddsd.dwHeight);
3194 GetWindowRect(window, &r);
3195 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3196 wine_dbgstr_rect(&r));
3198 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3199 expect_messages = normal_messages;
3200 screen_size.cx = 0;
3201 screen_size.cy = 0;
3203 hr = IDirectDrawSurface_IsLost(primary);
3204 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3205 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3206 devmode.dmPelsWidth = param.user32_width;
3207 devmode.dmPelsHeight = param.user32_height;
3208 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3209 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3210 hr = IDirectDrawSurface_IsLost(primary);
3211 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3213 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3214 expect_messages = NULL;
3215 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3217 GetWindowRect(window, &r);
3218 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3219 wine_dbgstr_rect(&r));
3221 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3222 expect_messages = normal_messages;
3223 screen_size.cx = 0;
3224 screen_size.cy = 0;
3226 hr = IDirectDrawSurface_Restore(primary);
3227 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3228 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3229 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
3231 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
3232 IDirectDrawSurface_Release(primary);
3233 IDirectDraw2_Release(ddraw);
3234 goto done;
3236 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3237 hr = IDirectDrawSurface_Restore(primary);
3238 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3239 hr = IDirectDrawSurface_IsLost(primary);
3240 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3242 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3243 expect_messages = NULL;
3244 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3246 GetWindowRect(window, &r);
3247 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3248 wine_dbgstr_rect(&r));
3250 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3251 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3252 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3253 registry_mode.dmPelsWidth, ddsd.dwWidth);
3254 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3255 registry_mode.dmPelsHeight, ddsd.dwHeight);
3256 IDirectDrawSurface_Release(primary);
3258 memset(&ddsd, 0, sizeof(ddsd));
3259 ddsd.dwSize = sizeof(ddsd);
3260 ddsd.dwFlags = DDSD_CAPS;
3261 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3263 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3264 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3265 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3266 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3267 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3268 param.ddraw_width, ddsd.dwWidth);
3269 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3270 param.ddraw_height, ddsd.dwHeight);
3272 GetWindowRect(window, &r);
3273 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3274 wine_dbgstr_rect(&r));
3276 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3277 expect_messages = normal_messages;
3278 screen_size.cx = 0;
3279 screen_size.cy = 0;
3281 hr = IDirectDrawSurface_IsLost(primary);
3282 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3283 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3284 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3285 hr = IDirectDrawSurface_IsLost(primary);
3286 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3288 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3289 expect_messages = NULL;
3290 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3292 GetWindowRect(window, &r);
3293 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3294 wine_dbgstr_rect(&r));
3296 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3297 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3298 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3299 param.ddraw_width, ddsd.dwWidth);
3300 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3301 param.ddraw_height, ddsd.dwHeight);
3302 IDirectDrawSurface_Release(primary);
3304 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3305 ok(ret, "Failed to get display mode.\n");
3306 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3307 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3308 "Expected resolution %ux%u, got %ux%u.\n",
3309 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3310 devmode.dmPelsWidth, devmode.dmPelsHeight);
3311 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3312 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3314 memset(&ddsd, 0, sizeof(ddsd));
3315 ddsd.dwSize = sizeof(ddsd);
3316 ddsd.dwFlags = DDSD_CAPS;
3317 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3319 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3320 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3321 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3322 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3323 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3324 registry_mode.dmPelsWidth, ddsd.dwWidth);
3325 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3326 registry_mode.dmPelsHeight, ddsd.dwHeight);
3328 GetWindowRect(window, &r);
3329 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3330 wine_dbgstr_rect(&r));
3332 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
3333 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
3334 * not DDSCL_FULLSCREEN. */
3335 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3336 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3338 GetWindowRect(window, &r);
3339 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3340 wine_dbgstr_rect(&r));
3342 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3343 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3344 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3345 registry_mode.dmPelsWidth, ddsd.dwWidth);
3346 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3347 registry_mode.dmPelsHeight, ddsd.dwHeight);
3348 IDirectDrawSurface_Release(primary);
3350 memset(&ddsd, 0, sizeof(ddsd));
3351 ddsd.dwSize = sizeof(ddsd);
3352 ddsd.dwFlags = DDSD_CAPS;
3353 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3355 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3356 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3357 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3358 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3359 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3360 registry_mode.dmPelsWidth, ddsd.dwWidth);
3361 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3362 registry_mode.dmPelsHeight, ddsd.dwHeight);
3364 GetWindowRect(window, &r);
3365 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3366 wine_dbgstr_rect(&r));
3368 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3369 expect_messages = normal_messages;
3370 screen_size.cx = 0;
3371 screen_size.cy = 0;
3373 hr = IDirectDrawSurface_IsLost(primary);
3374 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3375 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3376 devmode.dmPelsWidth = param.user32_width;
3377 devmode.dmPelsHeight = param.user32_height;
3378 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3379 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3380 hr = IDirectDrawSurface_IsLost(primary);
3381 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3383 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3384 expect_messages = NULL;
3385 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3387 GetWindowRect(window, &r);
3388 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3389 wine_dbgstr_rect(&r));
3391 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3392 expect_messages = normal_messages;
3393 screen_size.cx = 0;
3394 screen_size.cy = 0;
3396 hr = IDirectDrawSurface_Restore(primary);
3397 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3398 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3399 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3400 hr = IDirectDrawSurface_Restore(primary);
3401 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3402 hr = IDirectDrawSurface_IsLost(primary);
3403 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3405 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3406 expect_messages = NULL;
3407 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3409 GetWindowRect(window, &r);
3410 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3411 wine_dbgstr_rect(&r));
3413 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3414 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3415 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3416 registry_mode.dmPelsWidth, ddsd.dwWidth);
3417 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3418 registry_mode.dmPelsHeight, ddsd.dwHeight);
3419 IDirectDrawSurface_Release(primary);
3421 memset(&ddsd, 0, sizeof(ddsd));
3422 ddsd.dwSize = sizeof(ddsd);
3423 ddsd.dwFlags = DDSD_CAPS;
3424 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3426 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3427 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3428 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3429 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3430 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3431 param.ddraw_width, ddsd.dwWidth);
3432 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3433 param.ddraw_height, ddsd.dwHeight);
3435 GetWindowRect(window, &r);
3436 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3437 wine_dbgstr_rect(&r));
3439 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3440 expect_messages = normal_messages;
3441 screen_size.cx = 0;
3442 screen_size.cy = 0;
3444 hr = IDirectDrawSurface_IsLost(primary);
3445 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3446 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3447 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3448 hr = IDirectDrawSurface_IsLost(primary);
3449 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3451 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3452 expect_messages = NULL;
3453 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3455 GetWindowRect(window, &r);
3456 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3457 wine_dbgstr_rect(&r));
3459 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3460 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3461 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3462 param.ddraw_width, ddsd.dwWidth);
3463 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3464 param.ddraw_height, ddsd.dwHeight);
3465 IDirectDrawSurface_Release(primary);
3467 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3468 ok(ret, "Failed to get display mode.\n");
3469 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3470 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3471 "Expected resolution %ux%u, got %ux%u.\n",
3472 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3473 devmode.dmPelsWidth, devmode.dmPelsHeight);
3474 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3475 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3477 memset(&ddsd, 0, sizeof(ddsd));
3478 ddsd.dwSize = sizeof(ddsd);
3479 ddsd.dwFlags = DDSD_CAPS;
3480 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3482 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3483 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3484 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3485 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3486 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3487 registry_mode.dmPelsWidth, ddsd.dwWidth);
3488 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3489 registry_mode.dmPelsHeight, ddsd.dwHeight);
3490 IDirectDrawSurface_Release(primary);
3492 GetWindowRect(window, &r);
3493 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3494 wine_dbgstr_rect(&r));
3496 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3497 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3498 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3499 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3500 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3502 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3503 expect_messages = exclusive_messages;
3504 screen_size.cx = 0;
3505 screen_size.cy = 0;
3507 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3508 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3510 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3511 expect_messages = NULL;
3512 ok(screen_size.cx == registry_mode.dmPelsWidth
3513 && screen_size.cy == registry_mode.dmPelsHeight,
3514 "Expected screen size %ux%u, got %ux%u.\n",
3515 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3516 screen_size.cx, screen_size.cy);
3518 GetWindowRect(window, &r);
3519 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3520 wine_dbgstr_rect(&r));
3522 memset(&ddsd, 0, sizeof(ddsd));
3523 ddsd.dwSize = sizeof(ddsd);
3524 ddsd.dwFlags = DDSD_CAPS;
3525 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3527 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3528 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3529 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3530 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3531 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3532 registry_mode.dmPelsWidth, ddsd.dwWidth);
3533 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3534 registry_mode.dmPelsHeight, ddsd.dwHeight);
3535 IDirectDrawSurface_Release(primary);
3537 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3538 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3539 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3540 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3541 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3543 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3544 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3546 memset(&ddsd, 0, sizeof(ddsd));
3547 ddsd.dwSize = sizeof(ddsd);
3548 ddsd.dwFlags = DDSD_CAPS;
3549 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3551 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3552 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3553 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3554 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3555 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3556 param.ddraw_width, ddsd.dwWidth);
3557 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3558 param.ddraw_height, ddsd.dwHeight);
3559 IDirectDrawSurface_Release(primary);
3561 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3562 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3564 /* If the window is changed at the same time, messages are sent to the new window. */
3565 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3566 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3567 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3568 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3570 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3571 expect_messages = exclusive_messages;
3572 screen_size.cx = 0;
3573 screen_size.cy = 0;
3574 screen_size2.cx = 0;
3575 screen_size2.cy = 0;
3577 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3578 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3580 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3581 expect_messages = NULL;
3582 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
3583 screen_size.cx, screen_size.cy);
3584 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3585 "Expected screen size 2 %ux%u, got %ux%u.\n",
3586 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3588 GetWindowRect(window, &r);
3589 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3590 wine_dbgstr_rect(&r));
3591 GetWindowRect(window2, &r);
3592 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3593 wine_dbgstr_rect(&r));
3595 memset(&ddsd, 0, sizeof(ddsd));
3596 ddsd.dwSize = sizeof(ddsd);
3597 ddsd.dwFlags = DDSD_CAPS;
3598 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3600 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
3601 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3602 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
3603 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3604 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3605 registry_mode.dmPelsWidth, ddsd.dwWidth);
3606 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3607 registry_mode.dmPelsHeight, ddsd.dwHeight);
3608 IDirectDrawSurface_Release(primary);
3610 ref = IDirectDraw2_Release(ddraw);
3611 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3613 GetWindowRect(window, &r);
3614 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3615 wine_dbgstr_rect(&r));
3617 ret = restore_display_modes(original_modes, display_count);
3618 ok(ret, "Failed to restore display modes.\n");
3620 /* Test that no mode restorations if no mode changes happened */
3621 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3622 devmode.dmPelsWidth = param.user32_width;
3623 devmode.dmPelsHeight = param.user32_height;
3624 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3625 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
3627 ddraw = create_ddraw();
3628 ok(!!ddraw, "Failed to create a ddraw object.\n");
3629 ref = IDirectDraw2_Release(ddraw);
3630 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3632 memset(&devmode2, 0, sizeof(devmode2));
3633 devmode2.dmSize = sizeof(devmode2);
3634 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3635 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3636 ok(compare_mode_rect(&devmode2, &registry_mode), "Got a different mode.\n");
3637 ret = restore_display_modes(original_modes, display_count);
3638 ok(ret, "Failed to restore display modes.\n");
3640 /* Test that no mode restorations if no mode changes happened with fullscreen ddraw objects */
3641 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3642 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
3644 ddraw = create_ddraw();
3645 ok(!!ddraw, "Failed to create a ddraw object.\n");
3646 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3647 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
3648 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3649 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
3650 ref = IDirectDraw2_Release(ddraw);
3651 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3653 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3654 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3655 ok(compare_mode_rect(&devmode2, &registry_mode), "Got a different mode.\n");
3656 ret = restore_display_modes(original_modes, display_count);
3657 ok(ret, "Failed to restore display modes.\n");
3659 /* Test that mode restorations use display settings in the registry after ddraw object releases
3660 * if SetDisplayMode() was called */
3661 ddraw = create_ddraw();
3662 ok(!!ddraw, "Failed to create a ddraw object.\n");
3663 hr = set_display_mode(ddraw, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3664 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
3666 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3667 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
3669 ref = IDirectDraw2_Release(ddraw);
3670 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3672 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3673 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3674 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3675 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
3676 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3677 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3678 ret = restore_display_modes(original_modes, display_count);
3679 ok(ret, "Failed to restore display modes.\n");
3681 /* Test that mode restorations use display settings in the registry after RestoreDisplayMode() */
3682 ddraw = create_ddraw();
3683 ok(!!ddraw, "Failed to create a ddraw object.\n");
3684 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3685 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
3687 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3688 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
3690 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3691 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
3693 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3694 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3695 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3696 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
3697 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3698 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3700 ref = IDirectDraw2_Release(ddraw);
3701 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3703 done:
3704 expect_messages = NULL;
3705 DestroyWindow(window);
3706 DestroyWindow(window2);
3707 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3708 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3709 ret = restore_display_modes(original_modes, display_count);
3710 ok(ret, "Failed to restore display modes.\n");
3711 heap_free(original_modes);
3714 static void test_coop_level_mode_set_multi(void)
3716 DEVMODEW old_devmode, devmode, devmode2, devmode3, *original_modes = NULL;
3717 unsigned int mode_idx = 0, display_idx, display_count = 0;
3718 WCHAR second_monitor_name[CCHDEVICENAME];
3719 IDirectDraw2 *ddraw1, *ddraw2;
3720 LONG change_ret;
3721 UINT w, h;
3722 HWND window;
3723 HRESULT hr;
3724 ULONG ref;
3725 BOOL ret;
3727 memset(&devmode, 0, sizeof(devmode));
3728 devmode.dmSize = sizeof(devmode);
3729 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3730 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3731 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3732 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
3733 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3734 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3736 ret = save_display_modes(&original_modes, &display_count);
3737 ok(ret, "Failed to save original display modes.\n");
3739 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3740 0, 0, 100, 100, 0, 0, 0, 0);
3741 ddraw1 = create_ddraw();
3742 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3744 /* With just a single ddraw object, the display mode is restored on
3745 * release. */
3746 hr = set_display_mode(ddraw1, 800, 600);
3747 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
3749 win_skip("Broken SetDisplayMode(), skipping test.\n");
3750 IDirectDraw2_Release(ddraw1);
3751 DestroyWindow(window);
3752 return;
3754 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3755 w = GetSystemMetrics(SM_CXSCREEN);
3756 ok(w == 800, "Got unexpected screen width %u.\n", w);
3757 h = GetSystemMetrics(SM_CYSCREEN);
3758 ok(h == 600, "Got unexpected screen height %u.\n", h);
3760 ref = IDirectDraw2_Release(ddraw1);
3761 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3762 w = GetSystemMetrics(SM_CXSCREEN);
3763 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3764 h = GetSystemMetrics(SM_CYSCREEN);
3765 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3767 /* When there are multiple ddraw objects, the display mode is restored to
3768 * the initial mode, before the first SetDisplayMode() call. */
3769 ddraw1 = create_ddraw();
3770 hr = set_display_mode(ddraw1, 800, 600);
3771 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3772 w = GetSystemMetrics(SM_CXSCREEN);
3773 ok(w == 800, "Got unexpected screen width %u.\n", w);
3774 h = GetSystemMetrics(SM_CYSCREEN);
3775 ok(h == 600, "Got unexpected screen height %u.\n", h);
3777 ddraw2 = create_ddraw();
3778 hr = set_display_mode(ddraw2, 640, 480);
3779 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3780 w = GetSystemMetrics(SM_CXSCREEN);
3781 ok(w == 640, "Got unexpected screen width %u.\n", w);
3782 h = GetSystemMetrics(SM_CYSCREEN);
3783 ok(h == 480, "Got unexpected screen height %u.\n", h);
3785 ref = IDirectDraw2_Release(ddraw2);
3786 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3787 w = GetSystemMetrics(SM_CXSCREEN);
3788 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3789 h = GetSystemMetrics(SM_CYSCREEN);
3790 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3792 ref = IDirectDraw2_Release(ddraw1);
3793 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3794 w = GetSystemMetrics(SM_CXSCREEN);
3795 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3796 h = GetSystemMetrics(SM_CYSCREEN);
3797 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3799 /* Regardless of release ordering. */
3800 ddraw1 = create_ddraw();
3801 hr = set_display_mode(ddraw1, 800, 600);
3802 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3803 w = GetSystemMetrics(SM_CXSCREEN);
3804 ok(w == 800, "Got unexpected screen width %u.\n", w);
3805 h = GetSystemMetrics(SM_CYSCREEN);
3806 ok(h == 600, "Got unexpected screen height %u.\n", h);
3808 ddraw2 = create_ddraw();
3809 hr = set_display_mode(ddraw2, 640, 480);
3810 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3811 w = GetSystemMetrics(SM_CXSCREEN);
3812 ok(w == 640, "Got unexpected screen width %u.\n", w);
3813 h = GetSystemMetrics(SM_CYSCREEN);
3814 ok(h == 480, "Got unexpected screen height %u.\n", h);
3816 ref = IDirectDraw2_Release(ddraw1);
3817 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3818 w = GetSystemMetrics(SM_CXSCREEN);
3819 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3820 h = GetSystemMetrics(SM_CYSCREEN);
3821 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3823 ref = IDirectDraw2_Release(ddraw2);
3824 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3825 w = GetSystemMetrics(SM_CXSCREEN);
3826 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3827 h = GetSystemMetrics(SM_CYSCREEN);
3828 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3830 /* But only for ddraw objects that called SetDisplayMode(). */
3831 ddraw1 = create_ddraw();
3832 ddraw2 = create_ddraw();
3833 hr = set_display_mode(ddraw2, 640, 480);
3834 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3835 w = GetSystemMetrics(SM_CXSCREEN);
3836 ok(w == 640, "Got unexpected screen width %u.\n", w);
3837 h = GetSystemMetrics(SM_CYSCREEN);
3838 ok(h == 480, "Got unexpected screen height %u.\n", h);
3840 ref = IDirectDraw2_Release(ddraw1);
3841 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3842 w = GetSystemMetrics(SM_CXSCREEN);
3843 ok(w == 640, "Got unexpected screen width %u.\n", w);
3844 h = GetSystemMetrics(SM_CYSCREEN);
3845 ok(h == 480, "Got unexpected screen height %u.\n", h);
3847 ref = IDirectDraw2_Release(ddraw2);
3848 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3849 w = GetSystemMetrics(SM_CXSCREEN);
3850 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3851 h = GetSystemMetrics(SM_CYSCREEN);
3852 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3854 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3855 * restoring the display mode. */
3856 ddraw1 = create_ddraw();
3857 hr = set_display_mode(ddraw1, 800, 600);
3858 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3859 w = GetSystemMetrics(SM_CXSCREEN);
3860 ok(w == 800, "Got unexpected screen width %u.\n", w);
3861 h = GetSystemMetrics(SM_CYSCREEN);
3862 ok(h == 600, "Got unexpected screen height %u.\n", h);
3864 ddraw2 = create_ddraw();
3865 hr = set_display_mode(ddraw2, 640, 480);
3866 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3867 w = GetSystemMetrics(SM_CXSCREEN);
3868 ok(w == 640, "Got unexpected screen width %u.\n", w);
3869 h = GetSystemMetrics(SM_CYSCREEN);
3870 ok(h == 480, "Got unexpected screen height %u.\n", h);
3872 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3873 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3875 ref = IDirectDraw2_Release(ddraw1);
3876 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3877 w = GetSystemMetrics(SM_CXSCREEN);
3878 ok(w == 640, "Got unexpected screen width %u.\n", w);
3879 h = GetSystemMetrics(SM_CYSCREEN);
3880 ok(h == 480, "Got unexpected screen height %u.\n", h);
3882 ref = IDirectDraw2_Release(ddraw2);
3883 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3884 w = GetSystemMetrics(SM_CXSCREEN);
3885 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3886 h = GetSystemMetrics(SM_CYSCREEN);
3887 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3889 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3890 ddraw1 = create_ddraw();
3891 hr = set_display_mode(ddraw1, 800, 600);
3892 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3893 w = GetSystemMetrics(SM_CXSCREEN);
3894 ok(w == 800, "Got unexpected screen width %u.\n", w);
3895 h = GetSystemMetrics(SM_CYSCREEN);
3896 ok(h == 600, "Got unexpected screen height %u.\n", h);
3898 hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3899 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3901 ddraw2 = create_ddraw();
3902 hr = set_display_mode(ddraw2, 640, 480);
3903 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3905 ref = IDirectDraw2_Release(ddraw1);
3906 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3907 w = GetSystemMetrics(SM_CXSCREEN);
3908 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3909 h = GetSystemMetrics(SM_CYSCREEN);
3910 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3912 ref = IDirectDraw2_Release(ddraw2);
3913 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3914 w = GetSystemMetrics(SM_CXSCREEN);
3915 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3916 h = GetSystemMetrics(SM_CYSCREEN);
3917 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3919 if (display_count < 2)
3921 skip("Following tests require two monitors.\n");
3922 goto done;
3925 ret = restore_display_modes(original_modes, display_count);
3926 ok(ret, "Failed to restore display modes.\n");
3928 second_monitor_name[0] = '\0';
3929 for (display_idx = 0; display_idx < display_count; ++display_idx)
3931 if (original_modes[display_idx].dmPosition.x || original_modes[display_idx].dmPosition.y)
3933 lstrcpyW(second_monitor_name, original_modes[display_idx].dmDeviceName);
3934 break;
3937 ok(lstrlenW(second_monitor_name), "Got an empty second monitor name.\n");
3938 memset(&old_devmode, 0, sizeof(old_devmode));
3939 old_devmode.dmSize = sizeof(old_devmode);
3940 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
3941 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3943 devmode = old_devmode;
3944 while (EnumDisplaySettingsW(second_monitor_name, mode_idx++, &devmode))
3946 if (devmode.dmPelsWidth != old_devmode.dmPelsWidth
3947 || devmode.dmPelsHeight != old_devmode.dmPelsHeight)
3948 break;
3950 ok(devmode.dmPelsWidth != old_devmode.dmPelsWidth
3951 || devmode.dmPelsHeight != old_devmode.dmPelsHeight,
3952 "Failed to find a different mode for the second monitor.\n");
3954 /* Test that no mode restorations for non-primary monitors if SetDisplayMode() was not called */
3955 ddraw1 = create_ddraw();
3956 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3957 hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3958 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
3960 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
3961 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
3963 memset(&devmode2, 0, sizeof(devmode2));
3964 devmode2.dmSize = sizeof(devmode2);
3965 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
3966 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3967 if (compare_mode_rect(&devmode2, &old_devmode))
3969 skip("Failed to change display settings of the second monitor.\n");
3970 ref = IDirectDraw2_Release(ddraw1);
3971 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3972 goto done;
3975 hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_NORMAL);
3976 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
3977 ref = IDirectDraw2_Release(ddraw1);
3978 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3980 memset(&devmode3, 0, sizeof(devmode3));
3981 devmode3.dmSize = sizeof(devmode3);
3982 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode3);
3983 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3984 ok(compare_mode_rect(&devmode3, &devmode2), "Got a different mode.\n");
3985 ret = restore_display_modes(original_modes, display_count);
3986 ok(ret, "Failed to restore display modes.\n");
3988 /* Test that mode restorations happen for non-primary monitors on ddraw releases if
3989 * SetDisplayMode() was called */
3990 ddraw1 = create_ddraw();
3991 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3992 hr = set_display_mode(ddraw1, 800, 600);
3993 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
3995 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
3996 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
3998 ref = IDirectDraw2_Release(ddraw1);
3999 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4001 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4002 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4003 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4004 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4005 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4006 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4007 ret = restore_display_modes(original_modes, display_count);
4008 ok(ret, "Failed to restore display modes.\n");
4010 /* Test that mode restorations happen for non-primary monitors as well */
4011 ddraw1 = create_ddraw();
4012 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4013 hr = set_display_mode(ddraw1, 800, 600);
4014 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
4016 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4017 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
4019 hr = IDirectDraw2_RestoreDisplayMode(ddraw1);
4020 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
4022 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4023 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4024 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4025 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4026 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4027 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4029 ref = IDirectDraw2_Release(ddraw1);
4030 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4031 ret = restore_display_modes(original_modes, display_count);
4032 ok(ret, "Failed to restore display modes.\n");
4034 /* Test that mode restorations for non-primary monitors use display settings in the registry */
4035 ddraw1 = create_ddraw();
4036 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4037 hr = set_display_mode(ddraw1, 800, 600);
4038 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
4040 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
4041 CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
4042 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
4044 ref = IDirectDraw2_Release(ddraw1);
4045 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4047 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4048 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4049 ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
4050 "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
4051 devmode2.dmPelsWidth, devmode2.dmPelsHeight);
4052 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4053 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4054 ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
4055 "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
4056 devmode2.dmPelsWidth, devmode2.dmPelsHeight);
4057 ret = restore_display_modes(original_modes, display_count);
4058 ok(ret, "Failed to restore display modes.\n");
4060 /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
4061 * objects and one of them restores display mode */
4062 ddraw1 = create_ddraw();
4063 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4064 ddraw2 = create_ddraw();
4065 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4066 hr = set_display_mode(ddraw1, 800, 600);
4067 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
4068 hr = set_display_mode(ddraw2, 640, 480);
4069 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
4071 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4072 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
4074 hr = IDirectDraw2_RestoreDisplayMode(ddraw2);
4075 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
4077 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4078 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4079 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4080 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4081 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4082 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4084 ref = IDirectDraw2_Release(ddraw2);
4085 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4086 ref = IDirectDraw2_Release(ddraw1);
4087 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4088 ret = restore_display_modes(original_modes, display_count);
4089 ok(ret, "Failed to restore display modes.\n");
4091 /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
4092 * objects and one of them got released */
4093 ddraw1 = create_ddraw();
4094 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4095 ddraw2 = create_ddraw();
4096 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4097 hr = set_display_mode(ddraw1, 800, 600);
4098 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
4099 hr = set_display_mode(ddraw2, 640, 480);
4100 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
4102 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4103 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
4105 ref = IDirectDraw2_Release(ddraw2);
4106 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4108 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4109 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4110 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4111 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4112 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4113 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4115 ref = IDirectDraw2_Release(ddraw1);
4116 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4118 done:
4119 DestroyWindow(window);
4120 ret = restore_display_modes(original_modes, display_count);
4121 ok(ret, "Failed to restore display modes.\n");
4122 heap_free(original_modes);
4125 static void test_initialize(void)
4127 IDirectDraw2 *ddraw;
4128 HRESULT hr;
4130 ddraw = create_ddraw();
4131 ok(!!ddraw, "Failed to create a ddraw object.\n");
4133 hr = IDirectDraw2_Initialize(ddraw, NULL);
4134 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4135 IDirectDraw2_Release(ddraw);
4137 CoInitialize(NULL);
4138 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw2, (void **)&ddraw);
4139 ok(SUCCEEDED(hr), "Failed to create IDirectDraw2 instance, hr %#x.\n", hr);
4140 hr = IDirectDraw2_Initialize(ddraw, NULL);
4141 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4142 hr = IDirectDraw2_Initialize(ddraw, NULL);
4143 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4144 IDirectDraw2_Release(ddraw);
4145 CoUninitialize();
4148 static void test_coop_level_surf_create(void)
4150 IDirectDrawSurface *surface;
4151 IDirectDraw2 *ddraw;
4152 DDSURFACEDESC ddsd;
4153 HRESULT hr;
4155 ddraw = create_ddraw();
4156 ok(!!ddraw, "Failed to create a ddraw object.\n");
4158 memset(&ddsd, 0, sizeof(ddsd));
4159 ddsd.dwSize = sizeof(ddsd);
4160 ddsd.dwFlags = DDSD_CAPS;
4161 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4162 surface = (void *)0xdeadbeef;
4163 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4164 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4165 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4167 surface = (void *)0xdeadbeef;
4168 hr = IDirectDraw2_CreateSurface(ddraw, NULL, &surface, NULL);
4169 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4170 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4172 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4173 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4175 surface = (void *)0xdeadbeef;
4176 hr = IDirectDraw2_CreateSurface(ddraw, NULL, &surface, NULL);
4177 ok(hr == DDERR_INVALIDPARAMS, "Unexpected hr %#x.\n", hr);
4178 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4180 IDirectDraw2_Release(ddraw);
4183 static void test_coop_level_multi_window(void)
4185 HWND window1, window2;
4186 IDirectDraw2 *ddraw;
4187 HRESULT hr;
4189 window1 = create_window();
4190 window2 = create_window();
4191 ddraw = create_ddraw();
4192 ok(!!ddraw, "Failed to create a ddraw object.\n");
4194 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
4195 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4196 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
4197 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4198 ok(IsWindow(window1), "Window 1 was destroyed.\n");
4199 ok(IsWindow(window2), "Window 2 was destroyed.\n");
4201 IDirectDraw2_Release(ddraw);
4202 DestroyWindow(window2);
4203 DestroyWindow(window1);
4206 static void test_clear_rect_count(void)
4208 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4209 IDirect3DMaterial2 *white, *red, *green, *blue;
4210 IDirect3DViewport2 *viewport;
4211 IDirect3DDevice2 *device;
4212 IDirectDrawSurface *rt;
4213 IDirectDraw2 *ddraw;
4214 D3DCOLOR color;
4215 HWND window;
4216 HRESULT hr;
4218 window = create_window();
4219 ddraw = create_ddraw();
4220 ok(!!ddraw, "Failed to create a ddraw object.\n");
4221 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4223 skip("Failed to create a 3D device, skipping test.\n");
4224 IDirectDraw2_Release(ddraw);
4225 DestroyWindow(window);
4226 return;
4229 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
4230 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4232 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
4233 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
4234 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
4235 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
4237 viewport = create_viewport(device, 0, 0, 640, 480);
4238 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
4239 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
4241 viewport_set_background(device, viewport, white);
4242 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
4243 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4244 viewport_set_background(device, viewport, red);
4245 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
4246 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4247 viewport_set_background(device, viewport, green);
4248 hr = IDirect3DViewport2_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
4249 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4250 viewport_set_background(device, viewport, blue);
4251 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
4252 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4254 color = get_surface_color(rt, 320, 240);
4255 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x000000ff, 1)),
4256 "Got unexpected color 0x%08x.\n", color);
4258 IDirectDrawSurface_Release(rt);
4259 destroy_viewport(device, viewport);
4260 destroy_material(white);
4261 destroy_material(red);
4262 destroy_material(green);
4263 destroy_material(blue);
4264 IDirect3DDevice2_Release(device);
4265 IDirectDraw2_Release(ddraw);
4266 DestroyWindow(window);
4269 static BOOL test_mode_restored(IDirectDraw2 *ddraw, HWND window)
4271 DDSURFACEDESC ddsd1, ddsd2;
4272 HRESULT hr;
4274 memset(&ddsd1, 0, sizeof(ddsd1));
4275 ddsd1.dwSize = sizeof(ddsd1);
4276 hr = IDirectDraw2_GetDisplayMode(ddraw, &ddsd1);
4277 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4279 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4280 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4281 hr = set_display_mode(ddraw, 640, 480);
4282 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4283 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4284 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4286 memset(&ddsd2, 0, sizeof(ddsd2));
4287 ddsd2.dwSize = sizeof(ddsd2);
4288 hr = IDirectDraw2_GetDisplayMode(ddraw, &ddsd2);
4289 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4290 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
4291 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4293 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
4296 static void test_coop_level_versions(void)
4298 HWND window;
4299 IDirectDraw *ddraw;
4300 HRESULT hr;
4301 BOOL restored;
4302 IDirectDrawSurface *surface;
4303 IDirectDraw2 *ddraw2;
4304 DDSURFACEDESC ddsd;
4306 window = create_window();
4307 ddraw2 = create_ddraw();
4308 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4309 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
4310 restored = test_mode_restored(ddraw2, window);
4311 ok(restored, "Display mode not restored in new ddraw object\n");
4313 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
4314 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
4315 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4317 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4318 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4319 restored = test_mode_restored(ddraw2, window);
4320 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
4322 /* A successful one does */
4323 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4324 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4325 restored = test_mode_restored(ddraw2, window);
4326 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
4328 IDirectDraw_Release(ddraw);
4329 IDirectDraw2_Release(ddraw2);
4331 ddraw2 = create_ddraw();
4332 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4333 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
4334 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4336 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
4337 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4338 restored = test_mode_restored(ddraw2, window);
4339 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
4341 IDirectDraw_Release(ddraw);
4342 IDirectDraw2_Release(ddraw2);
4344 /* A failing call does not restore the ddraw2+ behavior */
4345 ddraw2 = create_ddraw();
4346 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4347 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
4348 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4350 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4351 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4352 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4353 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4354 restored = test_mode_restored(ddraw2, window);
4355 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
4357 IDirectDraw_Release(ddraw);
4358 IDirectDraw2_Release(ddraw2);
4360 /* Neither does a sequence of successful calls with the new interface */
4361 ddraw2 = create_ddraw();
4362 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4363 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
4364 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4366 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4367 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4368 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4369 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4370 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_NORMAL);
4371 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4373 restored = test_mode_restored(ddraw2, window);
4374 ok(!restored, "Display mode restored after ddraw1-ddraw2 SetCooperativeLevel() call sequence\n");
4375 IDirectDraw_Release(ddraw);
4376 IDirectDraw2_Release(ddraw2);
4378 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
4379 ddraw2 = create_ddraw();
4380 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4381 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
4382 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4384 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_NORMAL);
4385 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4387 memset(&ddsd, 0, sizeof(ddsd));
4388 ddsd.dwSize = sizeof(ddsd);
4389 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4390 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4391 ddsd.dwWidth = ddsd.dwHeight = 8;
4392 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4393 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4394 IDirectDrawSurface_Release(surface);
4395 restored = test_mode_restored(ddraw2, window);
4396 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
4398 IDirectDraw_Release(ddraw);
4399 IDirectDraw2_Release(ddraw2);
4400 DestroyWindow(window);
4403 static void test_lighting_interface_versions(void)
4405 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4406 IDirect3DMaterial2 *emissive, *background;
4407 IDirect3DViewport2 *viewport;
4408 IDirect3DDevice2 *device;
4409 IDirectDrawSurface *rt;
4410 IDirectDraw2 *ddraw;
4411 D3DCOLOR color;
4412 HWND window;
4413 HRESULT hr;
4414 D3DMATERIALHANDLE mat_handle;
4415 DWORD rs;
4416 unsigned int i;
4417 ULONG ref;
4418 static D3DVERTEX quad[] =
4420 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4421 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4422 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4423 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4425 static D3DLVERTEX lquad[] =
4427 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4428 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4429 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4430 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4432 static D3DTLVERTEX tlquad[] =
4434 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4435 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4436 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4437 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4439 static const struct
4441 D3DVERTEXTYPE vertextype;
4442 void *data;
4443 DWORD d3drs_lighting, d3drs_specular;
4444 DWORD draw_flags;
4445 D3DCOLOR color;
4447 tests[] =
4449 /* Lighting is enabled when D3DVT_VERTEX is used and D3DDP_DONOTLIGHT is not
4450 * set. D3DVT_VERTEX has diffuse = 0xffffffff and specular = 0x00000000, as
4451 * in later d3d versions */
4452 { D3DVT_VERTEX, quad, FALSE, FALSE, 0, 0x0000ff00},
4453 { D3DVT_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
4454 { D3DVT_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4455 { D3DVT_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4456 { D3DVT_VERTEX, quad, FALSE, TRUE, 0, 0x0000ff00},
4457 { D3DVT_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
4458 { D3DVT_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4459 { D3DVT_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4461 { D3DVT_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
4462 { D3DVT_LVERTEX, lquad, TRUE, FALSE, 0, 0x00ff0000},
4463 { D3DVT_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4464 { D3DVT_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4465 { D3DVT_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
4466 { D3DVT_LVERTEX, lquad, TRUE, TRUE, 0, 0x00ff8080},
4467 { D3DVT_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4468 { D3DVT_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4470 { D3DVT_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
4471 { D3DVT_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
4472 { D3DVT_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4473 { D3DVT_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4474 { D3DVT_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
4475 { D3DVT_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
4476 { D3DVT_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4477 { D3DVT_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4480 window = create_window();
4481 ddraw = create_ddraw();
4482 ok(!!ddraw, "Failed to create a ddraw object.\n");
4483 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4485 skip("Failed to create a 3D device, skipping test.\n");
4486 IDirectDraw2_Release(ddraw);
4487 DestroyWindow(window);
4488 return;
4491 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
4492 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4494 viewport = create_viewport(device, 0, 0, 640, 480);
4495 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
4496 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
4498 emissive = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
4499 hr = IDirect3DMaterial2_GetHandle(emissive, device, &mat_handle);
4500 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
4501 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
4502 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
4503 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4504 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
4506 background = create_diffuse_material(device, 0.1f, 0.1f, 0.1f, 0.1f);
4507 viewport_set_background(device, viewport, background);
4509 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
4510 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
4511 ok(rs == TRUE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected TRUE.\n", rs);
4513 for (i = 0; i < ARRAY_SIZE(tests); i++)
4515 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
4516 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4518 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
4519 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
4520 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
4521 tests[i].d3drs_specular);
4522 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
4524 hr = IDirect3DDevice2_BeginScene(device);
4525 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4526 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
4527 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
4528 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4529 hr = IDirect3DDevice2_EndScene(device);
4530 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4532 color = get_surface_color(rt, 320, 240);
4533 ok(compare_color(color, tests[i].color, 1),
4534 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
4535 color, tests[i].color, i);
4538 destroy_material(background);
4539 destroy_material(emissive);
4540 destroy_viewport(device, viewport);
4541 IDirectDrawSurface_Release(rt);
4542 IDirect3DDevice2_Release(device);
4543 ref = IDirectDraw2_Release(ddraw);
4544 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
4545 DestroyWindow(window);
4548 static struct
4550 BOOL received;
4551 IDirectDraw2 *ddraw;
4552 HWND window;
4553 DWORD coop_level;
4554 } activateapp_testdata;
4556 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
4558 if (message == WM_ACTIVATEAPP)
4560 if (activateapp_testdata.ddraw)
4562 HRESULT hr;
4563 activateapp_testdata.received = FALSE;
4564 hr = IDirectDraw2_SetCooperativeLevel(activateapp_testdata.ddraw,
4565 activateapp_testdata.window, activateapp_testdata.coop_level);
4566 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
4567 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
4569 activateapp_testdata.received = TRUE;
4572 return DefWindowProcA(hwnd, message, wparam, lparam);
4575 static void test_coop_level_activateapp(void)
4577 IDirectDraw2 *ddraw;
4578 HRESULT hr;
4579 HWND window;
4580 WNDCLASSA wc = {0};
4581 DDSURFACEDESC ddsd;
4582 IDirectDrawSurface *surface;
4584 ddraw = create_ddraw();
4585 ok(!!ddraw, "Failed to create a ddraw object.\n");
4587 wc.lpfnWndProc = activateapp_test_proc;
4588 wc.lpszClassName = "ddraw_test_wndproc_wc";
4589 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4591 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
4592 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
4594 /* Exclusive with window already active. */
4595 SetForegroundWindow(window);
4596 activateapp_testdata.received = FALSE;
4597 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4598 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4599 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
4600 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4601 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4603 /* Exclusive with window not active. */
4604 SetForegroundWindow(GetDesktopWindow());
4605 activateapp_testdata.received = FALSE;
4606 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4607 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4608 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4609 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4610 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4612 /* Normal with window not active, then exclusive with the same window. */
4613 SetForegroundWindow(GetDesktopWindow());
4614 activateapp_testdata.received = FALSE;
4615 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4616 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4617 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
4618 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4619 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4620 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4621 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4622 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4624 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
4625 SetForegroundWindow(GetDesktopWindow());
4626 activateapp_testdata.received = FALSE;
4627 activateapp_testdata.ddraw = ddraw;
4628 activateapp_testdata.window = window;
4629 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
4630 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4631 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4632 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4633 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4634 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4636 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
4637 * succeeding. Another switch to exclusive and back to normal is needed to release the
4638 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
4639 * WM_ACTIVATEAPP messages. */
4640 activateapp_testdata.ddraw = NULL;
4641 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4642 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4643 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4644 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4646 /* Setting DDSCL_NORMAL with recursive invocation. */
4647 SetForegroundWindow(GetDesktopWindow());
4648 activateapp_testdata.received = FALSE;
4649 activateapp_testdata.ddraw = ddraw;
4650 activateapp_testdata.window = window;
4651 activateapp_testdata.coop_level = DDSCL_NORMAL;
4652 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4653 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4654 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4656 /* DDraw is in exclusive mode now. */
4657 memset(&ddsd, 0, sizeof(ddsd));
4658 ddsd.dwSize = sizeof(ddsd);
4659 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4660 ddsd.dwBackBufferCount = 1;
4661 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4662 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4663 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4664 IDirectDrawSurface_Release(surface);
4666 /* Recover again, just to be sure. */
4667 activateapp_testdata.ddraw = NULL;
4668 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4669 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4670 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4671 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4673 DestroyWindow(window);
4674 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
4675 IDirectDraw2_Release(ddraw);
4678 struct format_support_check
4680 const DDPIXELFORMAT *format;
4681 BOOL supported;
4684 static HRESULT WINAPI test_unsupported_formats_cb(DDSURFACEDESC *desc, void *ctx)
4686 struct format_support_check *format = ctx;
4688 if (!memcmp(format->format, &desc->ddpfPixelFormat, sizeof(*format->format)))
4690 format->supported = TRUE;
4691 return DDENUMRET_CANCEL;
4694 return DDENUMRET_OK;
4697 static void test_unsupported_formats(void)
4699 HRESULT hr;
4700 BOOL expect_success;
4701 HWND window;
4702 IDirectDraw2 *ddraw;
4703 IDirect3DDevice2 *device;
4704 IDirectDrawSurface *surface;
4705 DDSURFACEDESC ddsd;
4706 unsigned int i, j;
4707 DWORD expected_caps;
4708 static const struct
4710 const char *name;
4711 DDPIXELFORMAT fmt;
4713 formats[] =
4716 "D3DFMT_A8R8G8B8",
4718 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
4719 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
4723 "D3DFMT_P8",
4725 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
4726 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
4730 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
4732 window = create_window();
4733 ddraw = create_ddraw();
4734 ok(!!ddraw, "Failed to create a ddraw object.\n");
4735 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4737 skip("Failed to create a 3D device, skipping test.\n");
4738 IDirectDraw2_Release(ddraw);
4739 DestroyWindow(window);
4740 return;
4743 for (i = 0; i < ARRAY_SIZE(formats); i++)
4745 struct format_support_check check = {&formats[i].fmt, FALSE};
4746 hr = IDirect3DDevice2_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
4747 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
4749 for (j = 0; j < ARRAY_SIZE(caps); j++)
4751 memset(&ddsd, 0, sizeof(ddsd));
4752 ddsd.dwSize = sizeof(ddsd);
4753 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4754 ddsd.ddpfPixelFormat = formats[i].fmt;
4755 ddsd.dwWidth = 4;
4756 ddsd.dwHeight = 4;
4757 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
4759 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
4760 expect_success = FALSE;
4761 else
4762 expect_success = TRUE;
4764 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4765 ok(SUCCEEDED(hr) == expect_success,
4766 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
4767 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
4768 if (FAILED(hr))
4769 continue;
4771 memset(&ddsd, 0, sizeof(ddsd));
4772 ddsd.dwSize = sizeof(ddsd);
4773 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
4774 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4776 if (caps[j] & DDSCAPS_VIDEOMEMORY)
4777 expected_caps = DDSCAPS_VIDEOMEMORY;
4778 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
4779 expected_caps = DDSCAPS_SYSTEMMEMORY;
4780 else if (check.supported)
4781 expected_caps = DDSCAPS_VIDEOMEMORY;
4782 else
4783 expected_caps = DDSCAPS_SYSTEMMEMORY;
4785 ok(ddsd.ddsCaps.dwCaps & expected_caps,
4786 "Expected capability %#x, format %s, input cap %#x.\n",
4787 expected_caps, formats[i].name, caps[j]);
4789 IDirectDrawSurface_Release(surface);
4793 IDirect3DDevice2_Release(device);
4794 IDirectDraw2_Release(ddraw);
4795 DestroyWindow(window);
4798 static void test_rt_caps(const GUID *device_guid)
4800 PALETTEENTRY palette_entries[256];
4801 IDirectDrawPalette *palette;
4802 IDirect3DDevice2 *device;
4803 BOOL software_device;
4804 IDirectDraw2 *ddraw;
4805 DWORD z_depth = 0;
4806 IDirect3D2 *d3d;
4807 DDCAPS hal_caps;
4808 unsigned int i;
4809 ULONG refcount;
4810 HWND window;
4811 HRESULT hr;
4813 static const DDPIXELFORMAT p8_fmt =
4815 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
4816 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
4819 static const struct
4821 const DDPIXELFORMAT *pf;
4822 DWORD caps_in;
4823 HRESULT create_device_hr;
4824 HRESULT set_rt_hr;
4825 HRESULT alternative_set_rt_hr;
4826 BOOL create_may_fail;
4828 test_data[] =
4831 NULL,
4832 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
4833 D3D_OK,
4834 D3D_OK,
4835 D3D_OK,
4836 FALSE,
4839 NULL,
4840 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4841 D3D_OK,
4842 D3D_OK,
4843 D3D_OK,
4844 FALSE,
4847 NULL,
4848 DDSCAPS_OFFSCREENPLAIN,
4849 DDERR_INVALIDCAPS,
4850 DDERR_INVALIDCAPS,
4851 DDERR_INVALIDCAPS,
4852 FALSE,
4855 NULL,
4856 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4857 D3DERR_SURFACENOTINVIDMEM,
4858 D3D_OK,
4859 D3D_OK,
4860 FALSE,
4863 NULL,
4864 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4865 DDERR_INVALIDCAPS,
4866 DDERR_INVALIDCAPS,
4867 DDERR_INVALIDCAPS,
4868 FALSE,
4871 NULL,
4872 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
4873 D3D_OK,
4874 D3D_OK,
4875 D3D_OK,
4876 FALSE,
4879 NULL,
4880 DDSCAPS_3DDEVICE,
4881 D3D_OK,
4882 D3D_OK,
4883 D3D_OK,
4884 FALSE,
4887 NULL,
4889 DDERR_INVALIDCAPS,
4890 DDERR_INVALIDCAPS,
4891 DDERR_INVALIDCAPS,
4892 FALSE,
4895 NULL,
4896 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4897 D3DERR_SURFACENOTINVIDMEM,
4898 D3D_OK,
4899 D3D_OK,
4900 FALSE,
4903 NULL,
4904 DDSCAPS_SYSTEMMEMORY,
4905 DDERR_INVALIDCAPS,
4906 DDERR_INVALIDCAPS,
4907 DDERR_INVALIDCAPS,
4908 FALSE,
4911 &p8_fmt,
4913 DDERR_INVALIDCAPS,
4914 DDERR_INVALIDCAPS,
4915 DDERR_INVALIDCAPS,
4916 FALSE,
4919 &p8_fmt,
4920 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4921 DDERR_NOPALETTEATTACHED,
4922 DDERR_INVALIDCAPS,
4923 DDERR_INVALIDCAPS,
4924 FALSE,
4927 &p8_fmt,
4928 DDSCAPS_OFFSCREENPLAIN,
4929 DDERR_INVALIDCAPS,
4930 DDERR_INVALIDCAPS,
4931 DDERR_INVALIDCAPS,
4932 FALSE,
4935 &p8_fmt,
4936 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
4937 DDERR_NOPALETTEATTACHED,
4938 DDERR_INVALIDCAPS,
4939 DDERR_INVALIDCAPS,
4940 FALSE,
4943 &p8_fmt,
4944 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4945 DDERR_INVALIDCAPS,
4946 DDERR_INVALIDCAPS,
4947 DDERR_INVALIDCAPS,
4948 FALSE,
4951 NULL,
4952 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
4953 DDERR_INVALIDCAPS,
4954 DDERR_INVALIDPIXELFORMAT,
4955 DDERR_INVALIDCAPS,
4956 TRUE /* AMD Evergreen */,
4959 NULL,
4960 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4961 DDERR_INVALIDCAPS,
4962 DDERR_INVALIDPIXELFORMAT,
4963 DDERR_INVALIDCAPS,
4964 FALSE,
4967 NULL,
4968 DDSCAPS_ZBUFFER,
4969 DDERR_INVALIDCAPS,
4970 DDERR_INVALIDCAPS,
4971 DDERR_INVALIDCAPS,
4972 FALSE,
4975 NULL,
4976 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
4977 DDERR_INVALIDCAPS,
4978 DDERR_INVALIDPIXELFORMAT,
4979 DDERR_INVALIDPIXELFORMAT,
4980 TRUE /* Nvidia Kepler */,
4983 NULL,
4984 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
4985 DDERR_INVALIDCAPS,
4986 DDERR_INVALIDCAPS,
4987 DDERR_INVALIDCAPS,
4988 TRUE /* Nvidia Kepler */,
4992 software_device = is_software_device_type(device_guid);
4994 window = create_window();
4995 ddraw = create_ddraw();
4996 ok(!!ddraw, "Failed to create a ddraw object.\n");
4997 if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid)))
4999 skip("Failed to create a 3D device, skipping test.\n");
5000 IDirectDraw2_Release(ddraw);
5001 DestroyWindow(window);
5002 return;
5004 z_depth = get_device_z_depth(device);
5005 ok(!!z_depth, "Failed to get device z depth.\n");
5006 IDirect3DDevice2_Release(device);
5008 if (FAILED(IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
5010 skip("D3D interface is not available, skipping test.\n");
5011 goto done;
5014 memset(palette_entries, 0, sizeof(palette_entries));
5015 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
5016 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
5018 memset(&hal_caps, 0, sizeof(hal_caps));
5019 hal_caps.dwSize = sizeof(hal_caps);
5020 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
5021 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
5023 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5025 IDirectDrawSurface *surface, *rt, *expected_rt, *tmp;
5026 DWORD caps_in, expected_caps;
5027 DDSURFACEDESC surface_desc;
5028 IDirect3DDevice2 *device;
5029 HRESULT expected_hr;
5031 caps_in = test_data[i].caps_in;
5033 memset(&surface_desc, 0, sizeof(surface_desc));
5034 surface_desc.dwSize = sizeof(surface_desc);
5035 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5036 surface_desc.ddsCaps.dwCaps = caps_in;
5037 if (test_data[i].pf)
5039 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5040 surface_desc.ddpfPixelFormat = *test_data[i].pf;
5042 if (caps_in & DDSCAPS_ZBUFFER)
5044 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
5045 U2(surface_desc).dwZBufferBitDepth = z_depth;
5047 surface_desc.dwWidth = 640;
5048 surface_desc.dwHeight = 480;
5049 if ((caps_in & DDSCAPS_VIDEOMEMORY) && !(hal_caps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
5050 expected_hr = DDERR_NODIRECTDRAWHW;
5051 else
5052 expected_hr = DD_OK;
5053 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5054 ok(hr == expected_hr || broken(test_data[i].create_may_fail
5055 || (software_device && test_data[i].pf == &p8_fmt && hr == DDERR_INVALIDPIXELFORMAT)),
5056 "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
5057 if (FAILED(hr))
5058 continue;
5060 memset(&surface_desc, 0, sizeof(surface_desc));
5061 surface_desc.dwSize = sizeof(surface_desc);
5062 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
5064 if ((caps_in & DDSCAPS_SYSTEMMEMORY) || !(hal_caps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
5065 expected_caps = caps_in | DDSCAPS_SYSTEMMEMORY;
5066 else
5067 expected_caps = caps_in | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
5069 ok(surface_desc.ddsCaps.dwCaps == expected_caps || (test_data[i].pf == &p8_fmt
5070 && surface_desc.ddsCaps.dwCaps == (caps_in | DDSCAPS_SYSTEMMEMORY))
5071 || (software_device && caps_in & DDSCAPS_ZBUFFER
5072 && surface_desc.ddsCaps.dwCaps == (caps_in | DDSCAPS_SYSTEMMEMORY)),
5073 "Got unexpected caps %#x, expected %#x, test %u, software_device %u.\n",
5074 surface_desc.ddsCaps.dwCaps, expected_caps, i, software_device);
5076 hr = IDirect3D2_CreateDevice(d3d, device_guid, surface, &device);
5078 ok((!software_device && hr == test_data[i].create_device_hr)
5079 || (software_device && (hr == (test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM
5080 ? DD_OK : test_data[i].create_device_hr))),
5081 "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
5083 if (FAILED(hr))
5085 if (hr == DDERR_NOPALETTEATTACHED)
5087 hr = IDirectDrawSurface_SetPalette(surface, palette);
5088 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
5089 hr = IDirect3D2_CreateDevice(d3d, device_guid, surface, &device);
5090 if (software_device)
5091 todo_wine
5092 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n",
5093 hr, i, software_device);
5094 else if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5095 ok(hr == DDERR_INVALIDPIXELFORMAT, "Got unexpected hr %#x, test %u, software_device %u.\n",
5096 hr, i, software_device);
5097 else
5098 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Got unexpected hr %#x, test %u, software_device %u.\n",
5099 hr, i, software_device);
5101 if (hr == DD_OK)
5103 refcount = IDirect3DDevice2_Release(device);
5104 ok(!refcount, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
5107 IDirectDrawSurface_Release(surface);
5109 memset(&surface_desc, 0, sizeof(surface_desc));
5110 surface_desc.dwSize = sizeof(surface_desc);
5111 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5112 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5113 surface_desc.dwWidth = 640;
5114 surface_desc.dwHeight = 480;
5115 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5116 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
5118 hr = IDirect3D2_CreateDevice(d3d, device_guid, surface, &device);
5119 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
5122 memset(&surface_desc, 0, sizeof(surface_desc));
5123 surface_desc.dwSize = sizeof(surface_desc);
5124 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5125 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5126 if (test_data[i].pf)
5128 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5129 surface_desc.ddpfPixelFormat = *test_data[i].pf;
5131 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
5133 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
5134 U2(surface_desc).dwZBufferBitDepth = z_depth;
5136 surface_desc.dwWidth = 640;
5137 surface_desc.dwHeight = 480;
5138 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &rt, NULL);
5139 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
5141 hr = IDirect3DDevice2_SetRenderTarget(device, rt, 0);
5142 ok(hr == test_data[i].set_rt_hr || (software_device && hr == DDERR_NOPALETTEATTACHED)
5143 || broken(hr == test_data[i].alternative_set_rt_hr),
5144 "Got unexpected hr %#x, test %u, software_device %u.\n",
5145 hr, i, software_device);
5147 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
5148 expected_rt = rt;
5149 else
5150 expected_rt = surface;
5152 /* It appears the surface is set as render target in this case, but no
5153 * reference is taken. */
5154 if (hr == DDERR_INVALIDPIXELFORMAT)
5156 refcount = IDirectDrawSurface_AddRef(rt);
5157 ok(refcount == 2, "Test %u: Got unexpected refcount %u.\n", i, refcount);
5160 hr = IDirect3DDevice2_GetRenderTarget(device, &tmp);
5161 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
5162 ok(tmp == expected_rt, "Got unexpected rt %p, test %u, software_device %u.\n", tmp, i, software_device);
5164 IDirectDrawSurface_Release(tmp);
5165 IDirectDrawSurface_Release(rt);
5166 refcount = IDirect3DDevice2_Release(device);
5167 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
5168 refcount = IDirectDrawSurface_Release(surface);
5169 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
5172 IDirectDrawPalette_Release(palette);
5173 IDirect3D2_Release(d3d);
5175 done:
5176 refcount = IDirectDraw2_Release(ddraw);
5177 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5178 DestroyWindow(window);
5181 static void test_primary_caps(void)
5183 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5184 IDirectDrawSurface *surface;
5185 DDSURFACEDESC surface_desc;
5186 IDirectDraw2 *ddraw;
5187 unsigned int i;
5188 ULONG refcount;
5189 HWND window;
5190 HRESULT hr;
5192 static const struct
5194 DWORD coop_level;
5195 DWORD caps_in;
5196 DWORD back_buffer_count;
5197 HRESULT hr;
5198 DWORD caps_out;
5200 test_data[] =
5203 DDSCL_NORMAL,
5204 DDSCAPS_PRIMARYSURFACE,
5205 ~0u,
5206 DD_OK,
5207 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
5210 DDSCL_NORMAL,
5211 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
5212 ~0u,
5213 DDERR_INVALIDCAPS,
5214 ~0u,
5217 DDSCL_NORMAL,
5218 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
5219 ~0u,
5220 DDERR_INVALIDCAPS,
5221 ~0u,
5224 DDSCL_NORMAL,
5225 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
5226 ~0u,
5227 DDERR_INVALIDCAPS,
5228 ~0u,
5231 DDSCL_NORMAL,
5232 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
5233 ~0u,
5234 DDERR_INVALIDCAPS,
5235 ~0u,
5238 DDSCL_NORMAL,
5239 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
5240 ~0u,
5241 DDERR_INVALIDCAPS,
5242 ~0u,
5245 DDSCL_NORMAL,
5246 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5247 ~0u,
5248 DDERR_INVALIDCAPS,
5249 ~0u,
5252 DDSCL_NORMAL,
5253 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5255 DDERR_INVALIDCAPS,
5256 ~0u,
5259 DDSCL_NORMAL,
5260 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5262 DDERR_NOEXCLUSIVEMODE,
5263 ~0u,
5266 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5267 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5269 DDERR_INVALIDCAPS,
5270 ~0u,
5273 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5274 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5276 DD_OK,
5277 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
5280 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5281 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
5283 DDERR_INVALIDCAPS,
5284 ~0u,
5287 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5288 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
5290 DDERR_INVALIDCAPS,
5291 ~0u,
5295 window = create_window();
5296 ddraw = create_ddraw();
5297 ok(!!ddraw, "Failed to create a ddraw object.\n");
5299 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5301 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
5302 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5304 memset(&surface_desc, 0, sizeof(surface_desc));
5305 surface_desc.dwSize = sizeof(surface_desc);
5306 surface_desc.dwFlags = DDSD_CAPS;
5307 if (test_data[i].back_buffer_count != ~0u)
5308 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5309 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5310 surface_desc.dwBackBufferCount = test_data[i].back_buffer_count;
5311 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5312 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
5313 if (FAILED(hr))
5314 continue;
5316 memset(&surface_desc, 0, sizeof(surface_desc));
5317 surface_desc.dwSize = sizeof(surface_desc);
5318 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
5319 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5320 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
5321 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5322 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5324 IDirectDrawSurface_Release(surface);
5327 refcount = IDirectDraw2_Release(ddraw);
5328 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5329 DestroyWindow(window);
5332 static void test_surface_lock(void)
5334 IDirectDraw2 *ddraw;
5335 IDirectDrawSurface *surface;
5336 IDirect3DDevice2 *device;
5337 HRESULT hr;
5338 HWND window;
5339 unsigned int i;
5340 DDSURFACEDESC ddsd;
5341 ULONG refcount;
5342 DWORD z_depth = 0;
5343 static const struct
5345 DWORD caps;
5346 const char *name;
5348 tests[] =
5351 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
5352 "videomemory offscreenplain"
5355 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5356 "systemmemory offscreenplain"
5359 DDSCAPS_PRIMARYSURFACE,
5360 "primary"
5363 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5364 "videomemory texture"
5367 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
5368 "systemmemory texture"
5371 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5372 "render target"
5375 DDSCAPS_ZBUFFER,
5376 "Z buffer"
5380 window = create_window();
5381 ddraw = create_ddraw();
5382 ok(!!ddraw, "Failed to create a ddraw object.\n");
5383 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
5385 skip("Failed to create a 3D device, skipping test.\n");
5386 IDirectDraw2_Release(ddraw);
5387 DestroyWindow(window);
5388 return;
5390 z_depth = get_device_z_depth(device);
5391 ok(!!z_depth, "Failed to get device z depth.\n");
5392 IDirect3DDevice2_Release(device);
5394 for (i = 0; i < ARRAY_SIZE(tests); i++)
5396 memset(&ddsd, 0, sizeof(ddsd));
5397 ddsd.dwSize = sizeof(ddsd);
5398 ddsd.dwFlags = DDSD_CAPS;
5399 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
5401 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5402 ddsd.dwWidth = 64;
5403 ddsd.dwHeight = 64;
5405 if (tests[i].caps & DDSCAPS_ZBUFFER)
5407 ddsd.dwFlags |= DDSD_ZBUFFERBITDEPTH;
5408 U2(ddsd).dwZBufferBitDepth = z_depth;
5410 ddsd.ddsCaps.dwCaps = tests[i].caps;
5412 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5413 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
5415 memset(&ddsd, 0, sizeof(ddsd));
5416 ddsd.dwSize = sizeof(ddsd);
5417 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5418 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
5419 if (SUCCEEDED(hr))
5421 hr = IDirectDrawSurface_Unlock(surface, NULL);
5422 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
5425 memset(&ddsd, 0, sizeof(ddsd));
5426 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5427 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, tests[i].name);
5429 IDirectDrawSurface_Release(surface);
5432 refcount = IDirectDraw2_Release(ddraw);
5433 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5434 DestroyWindow(window);
5437 static void test_surface_discard(void)
5439 IDirectDraw2 *ddraw;
5440 IDirect3DDevice2 *device;
5441 HRESULT hr;
5442 HWND window;
5443 DDSURFACEDESC ddsd;
5444 IDirectDrawSurface *surface, *target;
5445 void *addr;
5446 static const struct
5448 DWORD caps;
5449 BOOL discard;
5451 tests[] =
5453 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, TRUE},
5454 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, FALSE},
5455 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, TRUE},
5456 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, FALSE},
5458 unsigned int i;
5460 window = create_window();
5462 for (i = 0; i < ARRAY_SIZE(tests); i++)
5464 BOOL discarded;
5466 /* Sigh. Anything other than the first run of the loop randomly fails with
5467 * DDERR_SURFACELOST on my Radeon Pro 560 on Win10 19.09. Most of the time
5468 * the blit fails, but with sleeps added between surface creation and lock
5469 * the lock can fail too. Interestingly ddraw claims the render target has
5470 * been lost, not the test surface.
5472 * Recreating ddraw every iteration seems to fix this. */
5473 ddraw = create_ddraw();
5474 ok(!!ddraw, "Failed to create a ddraw object.\n");
5475 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
5477 skip("Failed to create a 3D device, skipping test.\n");
5478 DestroyWindow(window);
5479 IDirectDraw2_Release(ddraw);
5480 return;
5483 hr = IDirect3DDevice2_GetRenderTarget(device, &target);
5484 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5486 memset(&ddsd, 0, sizeof(ddsd));
5487 ddsd.dwSize = sizeof(ddsd);
5488 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5489 ddsd.ddsCaps.dwCaps = tests[i].caps;
5490 ddsd.dwWidth = 64;
5491 ddsd.dwHeight = 64;
5492 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5493 if (FAILED(hr))
5495 skip("Failed to create surface, skipping.\n");
5496 continue;
5499 memset(&ddsd, 0, sizeof(ddsd));
5500 ddsd.dwSize = sizeof(ddsd);
5501 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5502 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5503 addr = ddsd.lpSurface;
5504 hr = IDirectDrawSurface_Unlock(surface, NULL);
5505 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5507 memset(&ddsd, 0, sizeof(ddsd));
5508 ddsd.dwSize = sizeof(ddsd);
5509 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
5510 ok(SUCCEEDED(hr) , "Failed to lock surface, hr %#x.\n", hr);
5511 discarded = ddsd.lpSurface != addr;
5512 hr = IDirectDrawSurface_Unlock(surface, NULL);
5513 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5515 hr = IDirectDrawSurface_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
5516 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
5518 memset(&ddsd, 0, sizeof(ddsd));
5519 ddsd.dwSize = sizeof(ddsd);
5520 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
5521 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5522 discarded |= ddsd.lpSurface != addr;
5523 hr = IDirectDrawSurface_Unlock(surface, NULL);
5524 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5526 IDirectDrawSurface_Release(surface);
5528 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
5529 * AMD r500, evergreen). Windows XP, at least on AMD r200, never changes the pointer. */
5530 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
5532 IDirectDrawSurface_Release(target);
5533 IDirect3DDevice2_Release(device);
5534 IDirectDraw2_Release(ddraw);
5537 DestroyWindow(window);
5540 static void test_flip(void)
5542 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5543 IDirectDrawSurface *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
5544 DDSCAPS caps = {DDSCAPS_FLIP};
5545 DDSURFACEDESC surface_desc;
5546 BOOL sysmem_primary;
5547 IDirectDraw2 *ddraw;
5548 DWORD expected_caps;
5549 unsigned int i;
5550 D3DCOLOR color;
5551 ULONG refcount;
5552 HWND window;
5553 HRESULT hr;
5555 static const struct
5557 const char *name;
5558 DWORD caps;
5560 test_data[] =
5562 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
5563 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
5564 {"TEXTURE", DDSCAPS_TEXTURE},
5567 window = create_window();
5568 ddraw = create_ddraw();
5569 ok(!!ddraw, "Failed to create a ddraw object.\n");
5571 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5572 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5574 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5576 /* Creating a flippable texture induces a BSoD on some versions of the
5577 * Intel graphics driver. At least Intel GMA 950 with driver version
5578 * 6.14.10.4926 on Windows XP SP3 is affected. */
5579 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
5581 win_skip("Skipping flippable texture test.\n");
5582 continue;
5585 memset(&surface_desc, 0, sizeof(surface_desc));
5586 surface_desc.dwSize = sizeof(surface_desc);
5587 surface_desc.dwFlags = DDSD_CAPS;
5588 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
5589 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5590 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
5591 surface_desc.dwWidth = 512;
5592 surface_desc.dwHeight = 512;
5593 surface_desc.dwBackBufferCount = 3;
5594 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5595 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5597 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
5598 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5599 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5600 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5602 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
5603 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
5604 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5605 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5607 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
5608 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
5609 todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
5610 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
5611 if (FAILED(hr))
5612 continue;
5614 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
5615 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
5616 hr = IDirectDrawSurface_IsLost(frontbuffer);
5617 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5618 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
5619 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
5620 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5621 else
5622 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5623 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5624 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
5625 hr = IDirectDrawSurface_IsLost(frontbuffer);
5626 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5627 hr = restore_surfaces(ddraw);
5628 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
5630 memset(&surface_desc, 0, sizeof(surface_desc));
5631 surface_desc.dwSize = sizeof(surface_desc);
5632 hr = IDirectDrawSurface_GetSurfaceDesc(frontbuffer, &surface_desc);
5633 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
5634 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
5635 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
5636 expected_caps |= DDSCAPS_VISIBLE;
5637 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5638 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5639 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
5641 hr = IDirectDrawSurface_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
5642 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
5643 memset(&surface_desc, 0, sizeof(surface_desc));
5644 surface_desc.dwSize = sizeof(surface_desc);
5645 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer1, &surface_desc);
5646 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
5647 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
5648 test_data[i].name, surface_desc.dwBackBufferCount);
5649 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
5650 expected_caps |= DDSCAPS_BACKBUFFER;
5651 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5652 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5654 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
5655 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
5656 memset(&surface_desc, 0, sizeof(surface_desc));
5657 surface_desc.dwSize = sizeof(surface_desc);
5658 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer2, &surface_desc);
5659 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
5660 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
5661 test_data[i].name, surface_desc.dwBackBufferCount);
5662 expected_caps &= ~DDSCAPS_BACKBUFFER;
5663 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5664 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5666 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
5667 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
5668 memset(&surface_desc, 0, sizeof(surface_desc));
5669 surface_desc.dwSize = sizeof(surface_desc);
5670 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer3, &surface_desc);
5671 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
5672 ok(!surface_desc.dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
5673 test_data[i].name, surface_desc.dwBackBufferCount);
5674 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
5675 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
5677 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer3, &caps, &surface);
5678 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
5679 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
5680 test_data[i].name, surface, frontbuffer);
5681 IDirectDrawSurface_Release(surface);
5683 memset(&surface_desc, 0, sizeof(surface_desc));
5684 surface_desc.dwSize = sizeof(surface_desc);
5685 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5686 surface_desc.ddsCaps.dwCaps = 0;
5687 surface_desc.dwWidth = 640;
5688 surface_desc.dwHeight = 480;
5689 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5690 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
5691 hr = IDirectDrawSurface_Flip(frontbuffer, surface, DDFLIP_WAIT);
5692 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5693 IDirectDrawSurface_Release(surface);
5695 hr = IDirectDrawSurface_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
5696 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5697 hr = IDirectDrawSurface_Flip(backbuffer1, NULL, DDFLIP_WAIT);
5698 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5699 hr = IDirectDrawSurface_Flip(backbuffer2, NULL, DDFLIP_WAIT);
5700 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5701 hr = IDirectDrawSurface_Flip(backbuffer3, NULL, DDFLIP_WAIT);
5702 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
5704 /* The Nvidia Geforce 7 driver cannot do a color fill on a texture backbuffer after
5705 * the backbuffer has been locked or GetSurfaceDesc has been called. Do it ourselves
5706 * as a workaround. */
5707 fill_surface(backbuffer1, 0xffff0000);
5708 fill_surface(backbuffer2, 0xff00ff00);
5709 fill_surface(backbuffer3, 0xff0000ff);
5711 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
5712 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5713 color = get_surface_color(backbuffer1, 320, 240);
5714 /* The testbot seems to just copy the contents of one surface to all the
5715 * others, instead of properly flipping. */
5716 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
5717 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5718 color = get_surface_color(backbuffer2, 320, 240);
5719 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5720 fill_surface(backbuffer3, 0xffff0000);
5722 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
5723 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5724 color = get_surface_color(backbuffer1, 320, 240);
5725 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
5726 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5727 color = get_surface_color(backbuffer2, 320, 240);
5728 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5729 fill_surface(backbuffer3, 0xff00ff00);
5731 hr = IDirectDrawSurface_Flip(frontbuffer, NULL, DDFLIP_WAIT);
5732 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5733 color = get_surface_color(backbuffer1, 320, 240);
5734 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
5735 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5736 color = get_surface_color(backbuffer2, 320, 240);
5737 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5738 fill_surface(backbuffer3, 0xff0000ff);
5740 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
5741 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5742 color = get_surface_color(backbuffer2, 320, 240);
5743 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
5744 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5745 color = get_surface_color(backbuffer3, 320, 240);
5746 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5747 fill_surface(backbuffer1, 0xffff0000);
5749 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
5750 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5751 color = get_surface_color(backbuffer1, 320, 240);
5752 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5753 color = get_surface_color(backbuffer3, 320, 240);
5754 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
5755 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5756 fill_surface(backbuffer2, 0xff00ff00);
5758 hr = IDirectDrawSurface_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
5759 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
5760 color = get_surface_color(backbuffer1, 320, 240);
5761 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
5762 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5763 color = get_surface_color(backbuffer2, 320, 240);
5764 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
5766 IDirectDrawSurface_Release(backbuffer3);
5767 IDirectDrawSurface_Release(backbuffer2);
5768 IDirectDrawSurface_Release(backbuffer1);
5769 IDirectDrawSurface_Release(frontbuffer);
5772 refcount = IDirectDraw2_Release(ddraw);
5773 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5774 DestroyWindow(window);
5777 static void reset_ddsd(DDSURFACEDESC *ddsd)
5779 memset(ddsd, 0, sizeof(*ddsd));
5780 ddsd->dwSize = sizeof(*ddsd);
5783 static void test_set_surface_desc(void)
5785 IDirectDraw2 *ddraw;
5786 HWND window;
5787 HRESULT hr;
5788 DDSURFACEDESC ddsd;
5789 IDirectDrawSurface *surface;
5790 IDirectDrawSurface3 *surface3;
5791 BYTE data[16*16*4];
5792 ULONG ref;
5793 unsigned int i;
5794 static const struct
5796 DWORD caps;
5797 BOOL supported;
5798 const char *name;
5800 invalid_caps_tests[] =
5802 {DDSCAPS_VIDEOMEMORY, FALSE, "videomemory plain"},
5803 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, TRUE, "systemmemory texture"},
5804 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, FALSE, "systemmemory primary"},
5807 window = create_window();
5808 ddraw = create_ddraw();
5809 ok(!!ddraw, "Failed to create a ddraw object.\n");
5810 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5811 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5813 reset_ddsd(&ddsd);
5814 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
5815 ddsd.dwWidth = 8;
5816 ddsd.dwHeight = 8;
5817 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5818 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5819 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5820 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5821 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5822 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5823 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5825 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5826 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5828 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
5829 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
5830 IDirectDrawSurface_Release(surface);
5832 reset_ddsd(&ddsd);
5833 ddsd.dwFlags = DDSD_LPSURFACE;
5834 ddsd.lpSurface = data;
5835 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5836 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5838 /* Redundantly setting the same lpSurface is not an error. */
5839 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5840 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5841 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5842 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5843 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
5844 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
5846 hr = IDirectDrawSurface3_Lock(surface3, NULL, &ddsd, 0, NULL);
5847 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5848 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
5849 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
5850 hr = IDirectDrawSurface3_Unlock(surface3, NULL);
5851 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5853 reset_ddsd(&ddsd);
5854 ddsd.dwFlags = DDSD_LPSURFACE;
5855 ddsd.lpSurface = data;
5856 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 1);
5857 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
5859 ddsd.lpSurface = NULL;
5860 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5861 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
5863 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, NULL, 0);
5864 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
5866 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5867 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5868 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
5869 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
5871 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
5872 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5873 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
5875 ddsd.dwFlags = DDSD_CAPS;
5876 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5877 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
5879 /* dwCaps = 0 is allowed, but ignored. */
5880 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
5881 ddsd.lpSurface = data;
5882 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5883 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
5884 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5885 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5886 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
5887 ddsd.ddsCaps.dwCaps = 0;
5888 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5889 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5891 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5892 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5893 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
5894 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
5896 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
5897 reset_ddsd(&ddsd);
5898 ddsd.dwFlags = DDSD_HEIGHT;
5899 ddsd.dwHeight = 16;
5900 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5901 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
5903 ddsd.lpSurface = data;
5904 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
5905 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5906 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5908 ddsd.dwHeight = 0;
5909 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5910 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
5912 reset_ddsd(&ddsd);
5913 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5914 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
5915 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
5916 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
5918 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
5919 reset_ddsd(&ddsd);
5920 ddsd.dwFlags = DDSD_PITCH;
5921 U1(ddsd).lPitch = 8 * 4;
5922 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5923 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
5925 ddsd.dwFlags = DDSD_WIDTH;
5926 ddsd.dwWidth = 16;
5927 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5928 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
5930 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
5931 ddsd.lpSurface = data;
5932 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5933 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
5935 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
5936 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5937 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
5939 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5940 U1(ddsd).lPitch = 16 * 4;
5941 ddsd.dwWidth = 16;
5942 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5943 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5945 reset_ddsd(&ddsd);
5946 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
5947 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5948 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
5949 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
5950 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
5952 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
5954 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
5955 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5956 U1(ddsd).lPitch = 4 * 4;
5957 ddsd.lpSurface = data;
5958 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5959 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
5961 U1(ddsd).lPitch = 4;
5962 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5963 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
5965 U1(ddsd).lPitch = 16 * 4 + 1;
5966 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5967 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
5969 U1(ddsd).lPitch = 16 * 4 + 3;
5970 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5971 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
5973 U1(ddsd).lPitch = -4;
5974 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5975 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
5977 U1(ddsd).lPitch = 16 * 4;
5978 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5979 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5981 reset_ddsd(&ddsd);
5982 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5983 U1(ddsd).lPitch = 0;
5984 ddsd.dwWidth = 16;
5985 ddsd.lpSurface = data;
5986 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5987 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
5989 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
5990 U1(ddsd).lPitch = 16 * 4;
5991 ddsd.dwWidth = 0;
5992 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5993 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
5995 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
5996 ddsd.dwFlags = DDSD_PIXELFORMAT;
5997 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5998 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5999 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
6000 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6001 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6002 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6003 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6004 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
6006 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
6007 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6008 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6010 /* Can't set color keys. */
6011 reset_ddsd(&ddsd);
6012 ddsd.dwFlags = DDSD_CKSRCBLT;
6013 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
6014 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
6015 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6016 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6018 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
6019 ddsd.lpSurface = data;
6020 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6021 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6023 IDirectDrawSurface3_Release(surface3);
6025 /* Test mipmap texture. */
6026 reset_ddsd(&ddsd);
6027 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
6028 ddsd.dwWidth = 8;
6029 ddsd.dwHeight = 8;
6030 U2(ddsd).dwMipMapCount = 3;
6031 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6032 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
6033 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW || hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
6035 if (FAILED(hr))
6037 skip("Mipmaps are not supported.\n");
6039 else
6041 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
6042 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6043 IDirectDrawSurface_Release(surface);
6045 /* Changing surface desc for mipmap fails even without changing any
6046 * parameters. */
6047 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6048 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
6050 reset_ddsd(&ddsd);
6051 ddsd.dwFlags = DDSD_LPSURFACE;
6052 ddsd.lpSurface = data;
6053 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6054 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
6055 IDirectDrawSurface3_Release(surface3);
6058 reset_ddsd(&ddsd);
6059 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
6060 ddsd.dwWidth = 8;
6061 ddsd.dwHeight = 8;
6062 U2(ddsd).dwMipMapCount = 3;
6063 ddsd.lpSurface = data;
6064 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6066 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
6067 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW || hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
6069 if (hr == DD_OK)
6071 static DDSCAPS caps = {DDSCAPS_TEXTURE};
6072 IDirectDrawSurface3 *surface2;
6074 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
6075 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6076 IDirectDrawSurface_Release(surface);
6078 hr = IDirectDrawSurface3_GetAttachedSurface(surface3, &caps, &surface2);
6079 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6080 reset_ddsd(&ddsd);
6081 hr = IDirectDrawSurface3_GetSurfaceDesc(surface2, &ddsd);
6082 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6083 ok(ddsd.dwWidth == 4, "Got unexpected dwWidth %u.\n", ddsd.dwWidth);
6085 reset_ddsd(&ddsd);
6086 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
6087 ddsd.dwWidth = 16;
6088 ddsd.dwHeight = 16;
6089 U1(ddsd).lPitch = 16 * 4;
6090 ddsd.lpSurface = data;
6091 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6092 todo_wine ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6094 reset_ddsd(&ddsd);
6095 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
6096 ddsd.dwWidth = 8;
6097 ddsd.dwHeight = 8;
6098 U1(ddsd).lPitch = 8 * 4;
6099 ddsd.lpSurface = data;
6100 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6101 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6102 if (0)
6104 /* _Lock causes access violation on Windows. */
6105 reset_ddsd(&ddsd);
6106 hr = IDirectDrawSurface3_Lock(surface2, NULL, &ddsd, DDLOCK_WAIT, NULL);
6107 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6108 IDirectDrawSurface3_Unlock(surface2, NULL);
6111 if (0)
6113 /* Causes access violation on Windows. */
6114 reset_ddsd(&ddsd);
6115 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
6116 ddsd.dwWidth = 4;
6117 ddsd.dwHeight = 4;
6118 U1(ddsd).lPitch = 4 * 4;
6119 ddsd.lpSurface = data;
6120 hr = IDirectDrawSurface3_SetSurfaceDesc(surface2, &ddsd, 0);
6121 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6123 IDirectDrawSurface3_Release(surface2);
6124 IDirectDrawSurface3_Release(surface3);
6127 /* Test surface created with DDSD_LPSURFACE. */
6128 reset_ddsd(&ddsd);
6129 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LPSURFACE | DDSD_PITCH;
6130 ddsd.dwWidth = 8;
6131 ddsd.dwHeight = 8;
6132 ddsd.lpSurface = data;
6133 U1(ddsd).lPitch = 8 * 4;
6134 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6135 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
6136 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6138 /* SetSurfaceDesc needs systemmemory surfaces.
6140 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
6141 for (i = 0; i < ARRAY_SIZE(invalid_caps_tests); i++)
6143 reset_ddsd(&ddsd);
6144 ddsd.dwFlags = DDSD_CAPS;
6145 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
6146 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6148 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6149 ddsd.dwWidth = 8;
6150 ddsd.dwHeight = 8;
6151 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
6152 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
6153 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
6154 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6155 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6156 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6159 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
6160 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW, "Got unexpected hr %#x.\n", hr);
6161 if (FAILED(hr))
6163 skip("Cannot create a %s surface, skipping vidmem SetSurfaceDesc test.\n",
6164 invalid_caps_tests[i].name);
6165 goto done;
6167 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
6168 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6169 IDirectDrawSurface_Release(surface);
6171 reset_ddsd(&ddsd);
6172 ddsd.dwFlags = DDSD_LPSURFACE;
6173 ddsd.lpSurface = data;
6174 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6175 if (invalid_caps_tests[i].supported)
6177 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6179 else
6181 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6182 invalid_caps_tests[i].name, hr);
6184 /* Check priority of error conditions. */
6185 ddsd.dwFlags = DDSD_WIDTH;
6186 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6187 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6188 invalid_caps_tests[i].name, hr);
6191 IDirectDrawSurface3_Release(surface3);
6194 done:
6195 ref = IDirectDraw2_Release(ddraw);
6196 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6197 DestroyWindow(window);
6200 static void test_user_memory_getdc(void)
6202 IDirectDraw2 *ddraw;
6203 HWND window;
6204 HRESULT hr;
6205 DDSURFACEDESC ddsd;
6206 IDirectDrawSurface *surface;
6207 IDirectDrawSurface3 *surface3;
6208 DWORD data[16][16];
6209 HBITMAP bitmap;
6210 DIBSECTION dib;
6211 ULONG ref;
6212 int size;
6213 HDC dc;
6214 unsigned int x, y;
6216 window = create_window();
6217 ddraw = create_ddraw();
6218 ok(!!ddraw, "Failed to create a ddraw object.\n");
6220 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6221 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6223 reset_ddsd(&ddsd);
6224 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6225 ddsd.dwWidth = 16;
6226 ddsd.dwHeight = 16;
6227 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
6228 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
6229 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
6230 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6231 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6232 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6233 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6234 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
6235 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6237 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
6238 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
6239 IDirectDrawSurface_Release(surface);
6241 memset(data, 0xaa, sizeof(data));
6242 reset_ddsd(&ddsd);
6243 ddsd.dwFlags = DDSD_LPSURFACE;
6244 ddsd.lpSurface = data;
6245 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6246 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6248 hr = IDirectDrawSurface3_GetDC(surface3, &dc);
6249 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6250 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
6251 ok(!!bitmap, "Failed to get bitmap.\n");
6252 size = GetObjectA(bitmap, sizeof(dib), &dib);
6253 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
6254 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
6255 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
6256 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
6257 hr = IDirectDrawSurface3_ReleaseDC(surface3, dc);
6258 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6260 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
6261 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
6263 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
6264 ddsd.lpSurface = data;
6265 ddsd.dwWidth = 4;
6266 ddsd.dwHeight = 8;
6267 U1(ddsd).lPitch = sizeof(*data);
6268 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
6269 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6271 memset(data, 0xaa, sizeof(data));
6272 hr = IDirectDrawSurface3_GetDC(surface3, &dc);
6273 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6274 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
6275 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
6276 hr = IDirectDrawSurface3_ReleaseDC(surface3, dc);
6277 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6279 for (y = 0; y < 4; y++)
6281 for (x = 0; x < 4; x++)
6283 if ((x == 1 || x == 2) && (y == 1 || y == 2))
6284 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
6285 x, y, data[y][x]);
6286 else
6287 ok(data[y][x] == 0x00000000, "Expected color 0xaaaaaaaa on position %ux%u, got %#x.\n",
6288 x, y, data[y][x]);
6291 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
6292 data[0][5]);
6293 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
6294 data[7][3]);
6295 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
6296 data[7][4]);
6297 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
6298 data[8][0]);
6300 IDirectDrawSurface3_Release(surface3);
6301 ref = IDirectDraw2_Release(ddraw);
6302 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6303 DestroyWindow(window);
6306 static void test_sysmem_overlay(void)
6308 IDirectDraw2 *ddraw;
6309 HWND window;
6310 HRESULT hr;
6311 DDSURFACEDESC ddsd;
6312 IDirectDrawSurface *surface;
6313 ULONG ref;
6315 window = create_window();
6316 ddraw = create_ddraw();
6317 ok(!!ddraw, "Failed to create a ddraw object.\n");
6319 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6320 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6322 reset_ddsd(&ddsd);
6323 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
6324 ddsd.dwWidth = 16;
6325 ddsd.dwHeight = 16;
6326 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
6327 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
6328 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
6329 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
6330 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6331 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6332 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
6333 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
6334 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
6336 ref = IDirectDraw2_Release(ddraw);
6337 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6338 DestroyWindow(window);
6341 static void test_primary_palette(void)
6343 DDSCAPS surface_caps = {DDSCAPS_FLIP};
6344 IDirectDrawSurface *primary, *backbuffer;
6345 PALETTEENTRY palette_entries[256];
6346 IDirectDrawPalette *palette, *tmp;
6347 DDSURFACEDESC surface_desc;
6348 IDirectDraw2 *ddraw;
6349 DWORD palette_caps;
6350 ULONG refcount;
6351 HWND window;
6352 HRESULT hr;
6354 window = create_window();
6355 ddraw = create_ddraw();
6356 ok(!!ddraw, "Failed to create a ddraw object.\n");
6357 if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
6359 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
6360 IDirectDraw2_Release(ddraw);
6361 DestroyWindow(window);
6362 return;
6364 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6365 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6367 memset(&surface_desc, 0, sizeof(surface_desc));
6368 surface_desc.dwSize = sizeof(surface_desc);
6369 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6370 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6371 surface_desc.dwBackBufferCount = 1;
6372 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
6373 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6374 hr = IDirectDrawSurface_GetAttachedSurface(primary, &surface_caps, &backbuffer);
6375 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
6377 memset(palette_entries, 0, sizeof(palette_entries));
6378 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
6379 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6380 refcount = get_refcount((IUnknown *)palette);
6381 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6383 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6384 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6385 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6387 hr = IDirectDrawSurface_SetPalette(primary, palette);
6388 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6390 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
6391 * and is generally somewhat broken with respect to 8 bpp / palette
6392 * handling. */
6393 if (SUCCEEDED(IDirectDrawSurface_GetPalette(backbuffer, &tmp)))
6395 win_skip("Broken palette handling detected, skipping tests.\n");
6396 IDirectDrawPalette_Release(tmp);
6397 IDirectDrawPalette_Release(palette);
6398 /* The Windows 8 testbot keeps extra references to the primary and
6399 * backbuffer while in 8 bpp mode. */
6400 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
6401 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
6402 goto done;
6405 refcount = get_refcount((IUnknown *)palette);
6406 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6408 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6409 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6410 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
6411 "Got unexpected palette caps %#x.\n", palette_caps);
6413 hr = IDirectDrawSurface_SetPalette(primary, NULL);
6414 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6415 refcount = get_refcount((IUnknown *)palette);
6416 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6418 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6419 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6420 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6422 hr = IDirectDrawSurface_SetPalette(primary, palette);
6423 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6424 refcount = get_refcount((IUnknown *)palette);
6425 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6427 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
6428 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
6429 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
6430 IDirectDrawPalette_Release(tmp);
6431 hr = IDirectDrawSurface_GetPalette(backbuffer, &tmp);
6432 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6434 refcount = IDirectDrawPalette_Release(palette);
6435 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6436 refcount = IDirectDrawPalette_Release(palette);
6437 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6439 /* Note that this only seems to work when the palette is attached to the
6440 * primary surface. When attached to a regular surface, attempting to get
6441 * the palette here will cause an access violation. */
6442 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
6443 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6445 hr = IDirectDrawSurface_IsLost(primary);
6446 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6448 memset(&surface_desc, 0, sizeof(surface_desc));
6449 surface_desc.dwSize = sizeof(surface_desc);
6450 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
6451 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6452 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
6453 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
6454 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == 8, "Got unexpected bit count %u.\n",
6455 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
6457 hr = set_display_mode(ddraw, 640, 480);
6458 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
6460 memset(&surface_desc, 0, sizeof(surface_desc));
6461 surface_desc.dwSize = sizeof(surface_desc);
6462 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
6463 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6464 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
6465 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
6466 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == 32
6467 || U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == 24,
6468 "Got unexpected bit count %u.\n", U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
6470 hr = IDirectDrawSurface_IsLost(primary);
6471 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6472 hr = IDirectDrawSurface_Restore(primary);
6473 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
6474 hr = IDirectDrawSurface_IsLost(primary);
6475 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6477 memset(&surface_desc, 0, sizeof(surface_desc));
6478 surface_desc.dwSize = sizeof(surface_desc);
6479 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
6480 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6481 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
6482 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
6483 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == 32
6484 || U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == 24,
6485 "Got unexpected bit count %u.\n", U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
6487 done:
6488 refcount = IDirectDrawSurface_Release(backbuffer);
6489 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6490 refcount = IDirectDrawSurface_Release(primary);
6491 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6492 refcount = IDirectDraw2_Release(ddraw);
6493 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6494 DestroyWindow(window);
6497 static HRESULT WINAPI surface_counter(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
6499 UINT *surface_count = context;
6501 ++(*surface_count);
6502 IDirectDrawSurface_Release(surface);
6504 return DDENUMRET_OK;
6507 static void test_surface_attachment(void)
6509 IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
6510 DDSCAPS caps = {DDSCAPS_TEXTURE};
6511 DDSURFACEDESC surface_desc;
6512 IDirectDraw2 *ddraw;
6513 UINT surface_count;
6514 ULONG refcount;
6515 HWND window;
6516 HRESULT hr;
6518 window = create_window();
6519 ddraw = create_ddraw();
6520 ok(!!ddraw, "Failed to create a ddraw object.\n");
6521 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6522 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6524 memset(&surface_desc, 0, sizeof(surface_desc));
6525 surface_desc.dwSize = sizeof(surface_desc);
6526 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
6527 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6528 U2(surface_desc).dwMipMapCount = 3;
6529 surface_desc.dwWidth = 128;
6530 surface_desc.dwHeight = 128;
6531 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6532 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6534 hr = IDirectDrawSurface_GetAttachedSurface(surface1, &caps, &surface2);
6535 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
6536 hr = IDirectDrawSurface_GetAttachedSurface(surface2, &caps, &surface3);
6537 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
6538 hr = IDirectDrawSurface_GetAttachedSurface(surface3, &caps, &surface4);
6539 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6541 surface_count = 0;
6542 IDirectDrawSurface_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
6543 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6544 surface_count = 0;
6545 IDirectDrawSurface_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
6546 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6547 surface_count = 0;
6548 IDirectDrawSurface_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
6549 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
6551 memset(&surface_desc, 0, sizeof(surface_desc));
6552 surface_desc.dwSize = sizeof(surface_desc);
6553 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6554 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6555 surface_desc.dwWidth = 16;
6556 surface_desc.dwHeight = 16;
6557 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6558 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6560 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
6561 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6562 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
6563 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6564 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
6565 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6566 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
6567 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6568 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
6569 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6570 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
6571 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6573 IDirectDrawSurface_Release(surface4);
6575 memset(&surface_desc, 0, sizeof(surface_desc));
6576 surface_desc.dwSize = sizeof(surface_desc);
6577 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6578 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6579 surface_desc.dwWidth = 16;
6580 surface_desc.dwHeight = 16;
6581 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6582 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6584 if (SUCCEEDED(hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4)))
6586 skip("Running on refrast, skipping some tests.\n");
6587 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface4);
6588 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6590 else
6592 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6593 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
6594 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6595 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
6596 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6597 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
6598 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6599 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
6600 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6601 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
6602 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6605 IDirectDrawSurface_Release(surface4);
6606 IDirectDrawSurface_Release(surface3);
6607 IDirectDrawSurface_Release(surface2);
6608 IDirectDrawSurface_Release(surface1);
6610 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6611 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6613 /* Try a single primary and two offscreen plain surfaces. */
6614 memset(&surface_desc, 0, sizeof(surface_desc));
6615 surface_desc.dwSize = sizeof(surface_desc);
6616 surface_desc.dwFlags = DDSD_CAPS;
6617 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
6618 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6619 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6621 memset(&surface_desc, 0, sizeof(surface_desc));
6622 surface_desc.dwSize = sizeof(surface_desc);
6623 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6624 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6625 surface_desc.dwWidth = registry_mode.dmPelsWidth;
6626 surface_desc.dwHeight = registry_mode.dmPelsHeight;
6627 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
6628 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6630 memset(&surface_desc, 0, sizeof(surface_desc));
6631 surface_desc.dwSize = sizeof(surface_desc);
6632 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6633 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6634 surface_desc.dwWidth = registry_mode.dmPelsWidth;
6635 surface_desc.dwHeight = registry_mode.dmPelsHeight;
6636 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
6637 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6639 /* This one has a different size. */
6640 memset(&surface_desc, 0, sizeof(surface_desc));
6641 surface_desc.dwSize = sizeof(surface_desc);
6642 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6643 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6644 surface_desc.dwWidth = 128;
6645 surface_desc.dwHeight = 128;
6646 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6647 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6649 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
6650 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6651 /* Try the reverse without detaching first. */
6652 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
6653 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
6654 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
6655 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6657 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
6658 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6659 /* Try to detach reversed. */
6660 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
6661 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
6662 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
6663 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6665 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
6666 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6667 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
6668 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6670 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
6671 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6672 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
6673 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6675 IDirectDrawSurface_Release(surface4);
6676 IDirectDrawSurface_Release(surface3);
6677 IDirectDrawSurface_Release(surface2);
6678 IDirectDrawSurface_Release(surface1);
6680 /* Test depth surfaces of different sizes. */
6681 memset(&surface_desc, 0, sizeof(surface_desc));
6682 surface_desc.dwSize = sizeof(surface_desc);
6683 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6684 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6685 surface_desc.dwWidth = 64;
6686 surface_desc.dwHeight = 64;
6687 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6688 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
6690 memset(&surface_desc, 0, sizeof(surface_desc));
6691 surface_desc.dwSize = sizeof(surface_desc);
6692 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
6693 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
6694 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6695 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
6696 U1(surface_desc.ddpfPixelFormat).dwZBufferBitDepth = 16;
6697 U3(surface_desc.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
6698 surface_desc.dwWidth = 32;
6699 surface_desc.dwHeight = 32;
6700 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
6701 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
6702 surface_desc.dwWidth = 64;
6703 surface_desc.dwHeight = 64;
6704 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
6705 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
6706 surface_desc.dwWidth = 128;
6707 surface_desc.dwHeight = 128;
6708 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6709 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
6711 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
6712 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6713 if (SUCCEEDED(hr))
6714 IDirectDrawSurface2_DeleteAttachedSurface(surface1, 0, surface2);
6715 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface3);
6716 ok(hr == D3D_OK, "Failed to attach depth buffer, hr %#x.\n", hr);
6717 hr = IDirectDrawSurface2_DeleteAttachedSurface(surface1, 0, surface3);
6718 ok(hr == D3D_OK, "Failed to detach depth buffer, hr %#x.\n", hr);
6719 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
6720 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6722 IDirectDrawSurface2_Release(surface4);
6723 IDirectDrawSurface2_Release(surface3);
6724 IDirectDrawSurface2_Release(surface2);
6725 IDirectDrawSurface2_Release(surface1);
6727 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
6728 memset(&surface_desc, 0, sizeof(surface_desc));
6729 surface_desc.dwSize = sizeof(surface_desc);
6730 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6731 surface_desc.dwWidth = 64;
6732 surface_desc.dwHeight = 64;
6733 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6734 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
6735 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
6736 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
6737 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
6738 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
6739 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
6740 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6741 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6742 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
6743 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6745 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
6746 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
6747 U1(surface_desc.ddpfPixelFormat).dwZBufferBitDepth = 16;
6748 U3(surface_desc.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
6749 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
6750 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6752 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
6753 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6754 refcount = get_refcount((IUnknown *)surface2);
6755 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6756 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
6757 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
6759 /* Attaching while already attached to other surface. */
6760 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
6761 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6762 hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
6763 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6764 IDirectDrawSurface_Release(surface3);
6766 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
6767 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6768 refcount = get_refcount((IUnknown *)surface2);
6769 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6771 /* Automatic detachment on release. */
6772 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
6773 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6774 refcount = get_refcount((IUnknown *)surface2);
6775 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6776 refcount = IDirectDrawSurface_Release(surface1);
6777 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6778 refcount = IDirectDrawSurface_Release(surface2);
6779 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6780 refcount = IDirectDraw2_Release(ddraw);
6781 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6782 DestroyWindow(window);
6785 static void test_pixel_format(void)
6787 HWND window, window2 = NULL;
6788 HDC hdc, hdc2 = NULL;
6789 HMODULE gl = NULL;
6790 int format, test_format;
6791 PIXELFORMATDESCRIPTOR pfd;
6792 IDirectDraw2 *ddraw = NULL;
6793 IDirectDrawClipper *clipper = NULL;
6794 DDSURFACEDESC ddsd;
6795 IDirectDrawSurface *primary = NULL, *offscreen;
6796 DDBLTFX fx;
6797 HRESULT hr;
6799 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
6800 100, 100, 160, 160, NULL, NULL, NULL, NULL);
6801 if (!window)
6803 skip("Failed to create window\n");
6804 return;
6807 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
6808 100, 100, 160, 160, NULL, NULL, NULL, NULL);
6810 hdc = GetDC(window);
6811 if (!hdc)
6813 skip("Failed to get DC\n");
6814 goto cleanup;
6817 if (window2)
6818 hdc2 = GetDC(window2);
6820 gl = LoadLibraryA("opengl32.dll");
6821 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
6823 format = GetPixelFormat(hdc);
6824 ok(format == 0, "new window has pixel format %d\n", format);
6826 ZeroMemory(&pfd, sizeof(pfd));
6827 pfd.nSize = sizeof(pfd);
6828 pfd.nVersion = 1;
6829 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
6830 pfd.iPixelType = PFD_TYPE_RGBA;
6831 pfd.iLayerType = PFD_MAIN_PLANE;
6832 format = ChoosePixelFormat(hdc, &pfd);
6833 if (format <= 0)
6835 skip("no pixel format available\n");
6836 goto cleanup;
6839 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
6841 skip("failed to set pixel format\n");
6842 goto cleanup;
6845 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
6847 skip("failed to set pixel format on second window\n");
6848 if (hdc2)
6850 ReleaseDC(window2, hdc2);
6851 hdc2 = NULL;
6855 ddraw = create_ddraw();
6856 ok(!!ddraw, "Failed to create a ddraw object.\n");
6858 test_format = GetPixelFormat(hdc);
6859 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6861 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6862 if (FAILED(hr))
6864 skip("Failed to set cooperative level, hr %#x.\n", hr);
6865 goto cleanup;
6868 test_format = GetPixelFormat(hdc);
6869 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6871 if (hdc2)
6873 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
6874 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
6875 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
6876 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
6878 test_format = GetPixelFormat(hdc);
6879 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6881 test_format = GetPixelFormat(hdc2);
6882 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6885 memset(&ddsd, 0, sizeof(ddsd));
6886 ddsd.dwSize = sizeof(ddsd);
6887 ddsd.dwFlags = DDSD_CAPS;
6888 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
6890 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
6891 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
6893 test_format = GetPixelFormat(hdc);
6894 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6896 if (hdc2)
6898 test_format = GetPixelFormat(hdc2);
6899 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6902 if (clipper)
6904 hr = IDirectDrawSurface_SetClipper(primary, clipper);
6905 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
6907 test_format = GetPixelFormat(hdc);
6908 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6910 test_format = GetPixelFormat(hdc2);
6911 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6914 memset(&ddsd, 0, sizeof(ddsd));
6915 ddsd.dwSize = sizeof(ddsd);
6916 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6917 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6918 ddsd.dwWidth = ddsd.dwHeight = 64;
6919 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &offscreen, NULL);
6920 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
6922 memset(&fx, 0, sizeof(fx));
6923 fx.dwSize = sizeof(fx);
6924 hr = IDirectDrawSurface_Blt(offscreen, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
6925 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
6927 test_format = GetPixelFormat(hdc);
6928 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6930 hr = IDirectDrawSurface_Blt(primary, NULL, offscreen, NULL, DDBLT_WAIT, NULL);
6931 ok(SUCCEEDED(hr), "Failed to blit to primary surface, hr %#x.\n", hr);
6933 test_format = GetPixelFormat(hdc);
6934 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6936 if (hdc2)
6938 test_format = GetPixelFormat(hdc2);
6939 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
6942 IDirectDrawSurface_Release(offscreen);
6944 cleanup:
6945 if (primary) IDirectDrawSurface_Release(primary);
6946 if (clipper) IDirectDrawClipper_Release(clipper);
6947 if (ddraw) IDirectDraw2_Release(ddraw);
6948 if (gl) FreeLibrary(gl);
6949 if (hdc) ReleaseDC(window, hdc);
6950 if (hdc2) ReleaseDC(window2, hdc2);
6951 DestroyWindow(window);
6952 if (window2) DestroyWindow(window2);
6955 static void test_create_surface_pitch(void)
6957 IDirectDrawSurface *surface;
6958 DDSURFACEDESC surface_desc;
6959 IDirectDraw2 *ddraw;
6960 unsigned int i;
6961 ULONG refcount;
6962 HWND window;
6963 HRESULT hr;
6964 void *mem;
6966 static const struct
6968 DWORD caps;
6969 DWORD flags_in;
6970 DWORD pitch_in;
6971 HRESULT hr;
6972 DWORD flags_out;
6973 DWORD pitch_out32;
6974 DWORD pitch_out64;
6976 test_data[] =
6978 /* 0 */
6979 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6980 0, 0, DD_OK,
6981 DDSD_PITCH, 0x100, 0x100},
6982 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6983 DDSD_PITCH, 0x104, DD_OK,
6984 DDSD_PITCH, 0x100, 0x100},
6985 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6986 DDSD_PITCH, 0x0f8, DD_OK,
6987 DDSD_PITCH, 0x100, 0x100},
6988 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
6989 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
6990 0, 0, 0 },
6991 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6992 0, 0, DD_OK,
6993 DDSD_PITCH, 0x100, 0x0fc},
6994 /* 5 */
6995 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6996 DDSD_PITCH, 0x104, DD_OK,
6997 DDSD_PITCH, 0x100, 0x0fc},
6998 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
6999 DDSD_PITCH, 0x0f8, DD_OK,
7000 DDSD_PITCH, 0x100, 0x0fc},
7001 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7002 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
7003 DDSD_PITCH, 0x100, 0x0fc},
7004 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7005 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
7006 0, 0, 0 },
7007 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7008 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
7009 0, 0, 0 },
7010 /* 10 */
7011 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7012 0, 0, DDERR_INVALIDCAPS,
7013 0, 0, 0 },
7014 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7015 0, 0, DD_OK,
7016 DDSD_PITCH, 0x100, 0 },
7017 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7018 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7019 0, 0, 0 },
7020 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7021 0, 0, DDERR_INVALIDCAPS,
7022 0, 0, 0 },
7023 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7024 0, 0, DD_OK,
7025 DDSD_PITCH, 0x100, 0 },
7026 /* 15 */
7027 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7028 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
7029 0, 0, 0 },
7031 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
7033 window = create_window();
7034 ddraw = create_ddraw();
7035 ok(!!ddraw, "Failed to create a ddraw object.\n");
7036 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7037 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7039 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
7041 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7043 memset(&surface_desc, 0, sizeof(surface_desc));
7044 surface_desc.dwSize = sizeof(surface_desc);
7045 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
7046 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
7047 surface_desc.dwWidth = 63;
7048 surface_desc.dwHeight = 63;
7049 U1(surface_desc).lPitch = test_data[i].pitch_in;
7050 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7051 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
7052 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
7053 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7054 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7055 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
7056 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7057 if (test_data[i].flags_in & DDSD_LPSURFACE)
7059 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
7060 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
7061 surface_desc.lpSurface = mem;
7062 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7064 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
7065 continue;
7066 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
7067 if (FAILED(hr))
7068 continue;
7070 memset(&surface_desc, 0, sizeof(surface_desc));
7071 surface_desc.dwSize = sizeof(surface_desc);
7072 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
7073 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
7074 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
7075 "Test %u: Got unexpected flags %#x, expected %#x.\n",
7076 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
7077 /* The pitch for textures seems to be implementation specific. */
7078 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
7080 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
7081 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
7082 "Test %u: Got unexpected pitch %u, expected %u.\n",
7083 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
7084 else
7085 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
7086 "Test %u: Got unexpected pitch %u, expected %u.\n",
7087 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
7089 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
7091 IDirectDrawSurface_Release(surface);
7094 HeapFree(GetProcessHeap(), 0, mem);
7095 refcount = IDirectDraw2_Release(ddraw);
7096 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7097 DestroyWindow(window);
7100 static void test_mipmap(void)
7102 IDirectDrawSurface *surface1;
7103 IDirectDrawSurface2 *surface, *surface_base, *surface_mip;
7104 unsigned int i, mipmap_count;
7105 DDSURFACEDESC surface_desc;
7106 IDirectDraw2 *ddraw;
7107 ULONG refcount;
7108 HWND window;
7109 HRESULT hr;
7110 DDSCAPS caps = {DDSCAPS_COMPLEX};
7111 DDCAPS hal_caps;
7113 static const struct
7115 DWORD flags;
7116 DWORD caps;
7117 DWORD width;
7118 DWORD height;
7119 DWORD mipmap_count_in;
7120 HRESULT hr;
7121 DWORD mipmap_count_out;
7123 tests[] =
7125 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
7126 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
7127 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
7128 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
7129 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 6},
7130 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 6},
7133 window = create_window();
7134 ddraw = create_ddraw();
7135 ok(!!ddraw, "Failed to create a ddraw object.\n");
7136 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7137 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7139 memset(&hal_caps, 0, sizeof(hal_caps));
7140 hal_caps.dwSize = sizeof(hal_caps);
7141 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
7142 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7143 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7145 skip("Mipmapped textures not supported, skipping tests.\n");
7146 IDirectDraw2_Release(ddraw);
7147 DestroyWindow(window);
7148 return;
7151 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7153 memset(&surface_desc, 0, sizeof(surface_desc));
7154 surface_desc.dwSize = sizeof(surface_desc);
7155 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
7156 surface_desc.ddsCaps.dwCaps = tests[i].caps;
7157 surface_desc.dwWidth = tests[i].width;
7158 surface_desc.dwHeight = tests[i].height;
7159 if (tests[i].flags & DDSD_MIPMAPCOUNT)
7160 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
7161 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7162 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
7163 if (FAILED(hr))
7164 continue;
7166 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
7167 ok(SUCCEEDED(hr), "Test %u: Failed to get IDirectDrawSurface2 interface, hr %#x.\n", i, hr);
7168 IDirectDrawSurface_Release(surface1);
7170 memset(&surface_desc, 0, sizeof(surface_desc));
7171 surface_desc.dwSize = sizeof(surface_desc);
7172 hr = IDirectDrawSurface2_GetSurfaceDesc(surface, &surface_desc);
7173 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
7174 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
7175 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
7176 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
7177 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
7179 surface_base = surface;
7180 IDirectDrawSurface2_AddRef(surface_base);
7181 mipmap_count = U2(surface_desc).dwMipMapCount;
7182 while (mipmap_count > 1)
7184 hr = IDirectDrawSurface2_GetAttachedSurface(surface_base, &caps, &surface_mip);
7185 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get attached surface, hr %#x.\n", i, mipmap_count, hr);
7187 memset(&surface_desc, 0, sizeof(surface_desc));
7188 surface_desc.dwSize = sizeof(surface_desc);
7189 hr = IDirectDrawSurface2_GetSurfaceDesc(surface_base, &surface_desc);
7190 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get surface desc, hr %#x.\n", i, mipmap_count, hr);
7191 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
7192 "Test %u, %u: Got unexpected flags %#x.\n", i, mipmap_count, surface_desc.dwFlags);
7193 ok(U2(surface_desc).dwMipMapCount == mipmap_count,
7194 "Test %u, %u: Got unexpected mipmap count %u.\n",
7195 i, mipmap_count, U2(surface_desc).dwMipMapCount);
7197 memset(&surface_desc, 0, sizeof(surface_desc));
7198 surface_desc.dwSize = sizeof(surface_desc);
7199 hr = IDirectDrawSurface2_Lock(surface_base, NULL, &surface_desc, 0, NULL);
7200 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
7201 ok(surface_desc.dwMipMapCount == mipmap_count,
7202 "Test %u, %u: unexpected change of mipmap count %u.\n",
7203 i, mipmap_count, surface_desc.dwMipMapCount);
7204 memset(&surface_desc, 0, sizeof(surface_desc));
7205 surface_desc.dwSize = sizeof(surface_desc);
7206 hr = IDirectDrawSurface2_Lock(surface_mip, NULL, &surface_desc, 0, NULL);
7207 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
7208 ok(surface_desc.dwMipMapCount == mipmap_count - 1,
7209 "Test %u, %u: Child mipmap count unexpected %u\n", i, mipmap_count, surface_desc.dwMipMapCount);
7210 IDirectDrawSurface2_Unlock(surface_mip, NULL);
7211 IDirectDrawSurface2_Unlock(surface_base, NULL);
7213 IDirectDrawSurface2_Release(surface_base);
7214 surface_base = surface_mip;
7215 --mipmap_count;
7217 IDirectDrawSurface2_Release(surface_base);
7219 IDirectDrawSurface2_Release(surface);
7222 refcount = IDirectDraw2_Release(ddraw);
7223 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7224 DestroyWindow(window);
7227 static void test_palette_complex(void)
7229 IDirectDrawSurface *surface1;
7230 IDirectDrawSurface2 *surface, *mipmap, *tmp;
7231 DDSURFACEDESC surface_desc;
7232 IDirectDraw2 *ddraw;
7233 IDirectDrawPalette *palette, *palette2, *palette_mipmap;
7234 ULONG refcount;
7235 HWND window;
7236 HRESULT hr;
7237 DDSCAPS caps = {DDSCAPS_COMPLEX};
7238 DDCAPS hal_caps;
7239 PALETTEENTRY palette_entries[256];
7240 unsigned int i;
7241 HDC dc;
7242 RGBQUAD rgbquad;
7243 UINT count;
7245 window = create_window();
7246 ddraw = create_ddraw();
7247 ok(!!ddraw, "Failed to create a ddraw object.\n");
7248 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7249 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7251 memset(&hal_caps, 0, sizeof(hal_caps));
7252 hal_caps.dwSize = sizeof(hal_caps);
7253 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
7254 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7255 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7257 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
7258 IDirectDraw2_Release(ddraw);
7259 DestroyWindow(window);
7260 return;
7263 memset(&surface_desc, 0, sizeof(surface_desc));
7264 surface_desc.dwSize = sizeof(surface_desc);
7265 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7266 surface_desc.dwWidth = 128;
7267 surface_desc.dwHeight = 128;
7268 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7269 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7270 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7271 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
7272 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7273 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7274 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
7275 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#x.\n", hr);
7276 IDirectDrawSurface_Release(surface1);
7278 memset(palette_entries, 0, sizeof(palette_entries));
7279 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7280 palette_entries, &palette, NULL);
7281 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7283 memset(palette_entries, 0, sizeof(palette_entries));
7284 palette_entries[1].peRed = 0xff;
7285 palette_entries[1].peGreen = 0x80;
7286 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7287 palette_entries, &palette_mipmap, NULL);
7288 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7290 palette2 = (void *)0xdeadbeef;
7291 hr = IDirectDrawSurface2_GetPalette(surface, &palette2);
7292 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7293 ok(!palette2, "Got unexpected palette %p.\n", palette2);
7294 hr = IDirectDrawSurface2_SetPalette(surface, palette);
7295 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7296 hr = IDirectDrawSurface2_GetPalette(surface, &palette2);
7297 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
7298 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
7299 IDirectDrawPalette_Release(palette2);
7301 mipmap = surface;
7302 IDirectDrawSurface2_AddRef(mipmap);
7303 for (i = 0; i < 7; ++i)
7305 hr = IDirectDrawSurface2_GetAttachedSurface(mipmap, &caps, &tmp);
7306 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
7307 palette2 = (void *)0xdeadbeef;
7308 hr = IDirectDrawSurface2_GetPalette(tmp, &palette2);
7309 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
7310 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
7312 hr = IDirectDrawSurface2_SetPalette(tmp, palette_mipmap);
7313 ok(SUCCEEDED(hr), "Failed to set palette, i %u, hr %#x.\n", i, hr);
7315 hr = IDirectDrawSurface2_GetPalette(tmp, &palette2);
7316 ok(SUCCEEDED(hr), "Failed to get palette, i %u, hr %#x.\n", i, hr);
7317 ok(palette_mipmap == palette2, "Got unexpected palette %p.\n", palette2);
7318 IDirectDrawPalette_Release(palette2);
7320 hr = IDirectDrawSurface2_GetDC(tmp, &dc);
7321 ok(SUCCEEDED(hr), "Failed to get DC, i %u, hr %#x.\n", i, hr);
7322 count = GetDIBColorTable(dc, 1, 1, &rgbquad);
7323 ok(count == 1, "Expected count 1, got %u.\n", count);
7324 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x.\n", rgbquad.rgbRed);
7325 ok(rgbquad.rgbGreen == 0x80, "Expected rgbGreen = 0x80, got %#x.\n", rgbquad.rgbGreen);
7326 ok(rgbquad.rgbBlue == 0x0, "Expected rgbBlue = 0x0, got %#x.\n", rgbquad.rgbBlue);
7327 hr = IDirectDrawSurface2_ReleaseDC(tmp, dc);
7328 ok(SUCCEEDED(hr), "Failed to release DC, i %u, hr %#x.\n", i, hr);
7330 IDirectDrawSurface2_Release(mipmap);
7331 mipmap = tmp;
7334 hr = IDirectDrawSurface2_GetAttachedSurface(mipmap, &caps, &tmp);
7335 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7336 IDirectDrawSurface2_Release(mipmap);
7337 refcount = IDirectDrawSurface2_Release(surface);
7338 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7339 refcount = IDirectDrawPalette_Release(palette_mipmap);
7340 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7341 refcount = IDirectDrawPalette_Release(palette);
7342 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7344 refcount = IDirectDraw2_Release(ddraw);
7345 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7346 DestroyWindow(window);
7349 static void test_p8_blit(void)
7351 IDirectDrawSurface *src, *dst, *dst_p8;
7352 DDSURFACEDESC surface_desc;
7353 IDirectDraw2 *ddraw;
7354 IDirectDrawPalette *palette, *palette2;
7355 ULONG refcount;
7356 HWND window;
7357 HRESULT hr;
7358 PALETTEENTRY palette_entries[256];
7359 unsigned int x;
7360 DDBLTFX fx;
7361 BOOL is_warp;
7362 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
7363 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
7364 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
7365 static const D3DCOLOR expected[] =
7367 0x00101010, 0x00010101, 0x00020202, 0x00030303,
7368 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
7370 D3DCOLOR color;
7372 window = create_window();
7373 ddraw = create_ddraw();
7374 ok(!!ddraw, "Failed to create a ddraw object.\n");
7375 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7376 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7377 is_warp = ddraw_is_warp(ddraw);
7379 memset(palette_entries, 0, sizeof(palette_entries));
7380 palette_entries[1].peGreen = 0xff;
7381 palette_entries[2].peBlue = 0xff;
7382 palette_entries[3].peFlags = 0xff;
7383 palette_entries[4].peRed = 0xff;
7384 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7385 palette_entries, &palette, NULL);
7386 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7387 palette_entries[1].peBlue = 0xff;
7388 palette_entries[2].peGreen = 0xff;
7389 palette_entries[3].peRed = 0xff;
7390 palette_entries[4].peFlags = 0x0;
7391 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7392 palette_entries, &palette2, NULL);
7393 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7395 memset(&surface_desc, 0, sizeof(surface_desc));
7396 surface_desc.dwSize = sizeof(surface_desc);
7397 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7398 surface_desc.dwWidth = 8;
7399 surface_desc.dwHeight = 1;
7400 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7401 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7402 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7403 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
7404 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src, NULL);
7405 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7406 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
7407 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7408 hr = IDirectDrawSurface_SetPalette(dst_p8, palette2);
7409 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7411 memset(&surface_desc, 0, sizeof(surface_desc));
7412 surface_desc.dwSize = sizeof(surface_desc);
7413 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7414 surface_desc.dwWidth = 8;
7415 surface_desc.dwHeight = 1;
7416 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7417 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
7418 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
7419 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
7420 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7421 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7422 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
7423 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
7424 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst, NULL);
7425 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7427 memset(&surface_desc, 0, sizeof(surface_desc));
7428 surface_desc.dwSize = sizeof(surface_desc);
7429 hr = IDirectDrawSurface_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
7430 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
7431 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
7432 hr = IDirectDrawSurface_Unlock(src, NULL);
7433 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
7435 hr = IDirectDrawSurface_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
7436 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
7437 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
7438 hr = IDirectDrawSurface_Unlock(dst_p8, NULL);
7439 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
7441 fx.dwSize = sizeof(fx);
7442 fx.dwFillColor = 0xdeadbeef;
7443 hr = IDirectDrawSurface_Blt(dst, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
7444 ok(SUCCEEDED(hr), "Failed to color fill %#x.\n", hr);
7446 hr = IDirectDrawSurface_SetPalette(src, palette);
7447 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7448 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
7449 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
7450 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
7451 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
7452 "Failed to blit, hr %#x.\n", hr);
7454 if (SUCCEEDED(hr))
7456 for (x = 0; x < ARRAY_SIZE(expected); x++)
7458 color = get_surface_color(dst, x, 0);
7459 /* WARP on 1709 and newer write zeroes on non-colorkeyed P8 -> RGB blits. For ckey
7460 * blits see below. */
7461 todo_wine ok(compare_color(color, expected[x], 0)
7462 || broken(is_warp && compare_color(color, 0x00000000, 0)),
7463 "Pixel %u: Got color %#x, expected %#x.\n",
7464 x, color, expected[x]);
7468 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
7469 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
7470 hr = IDirectDrawSurface7_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
7471 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
7473 hr = IDirectDrawSurface_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
7474 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
7475 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
7476 * surface untouched. Error checking (DDBLT_KEYSRC without a key
7477 * for example) also works as expected.
7479 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
7480 * the display mode set to P8 doesn't help either. */
7481 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
7482 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
7483 "Got unexpected P8 color key blit result.\n");
7484 hr = IDirectDrawSurface_Unlock(dst_p8, NULL);
7485 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
7487 IDirectDrawSurface_Release(src);
7488 IDirectDrawSurface_Release(dst);
7489 IDirectDrawSurface_Release(dst_p8);
7490 IDirectDrawPalette_Release(palette);
7491 IDirectDrawPalette_Release(palette2);
7493 refcount = IDirectDraw2_Release(ddraw);
7494 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7495 DestroyWindow(window);
7498 static void test_material(void)
7500 IDirect3DMaterial2 *background, *material;
7501 D3DMATERIALHANDLE mat_handle, tmp;
7502 IDirect3DViewport2 *viewport;
7503 IDirect3DDevice2 *device;
7504 IDirectDrawSurface *rt;
7505 IDirectDraw2 *ddraw;
7506 D3DCOLOR color;
7507 ULONG refcount;
7508 unsigned int i;
7509 HWND window;
7510 HRESULT hr;
7511 BOOL valid;
7513 static D3DVERTEX quad[] =
7515 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
7516 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
7517 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
7518 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
7520 static const struct
7522 BOOL material;
7523 D3DCOLOR expected_color;
7525 test_data[] =
7527 {TRUE, 0x0000ff00},
7528 {FALSE, 0x00ffffff},
7530 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
7532 window = create_window();
7533 ddraw = create_ddraw();
7534 ok(!!ddraw, "Failed to create a ddraw object.\n");
7535 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7537 skip("Failed to create a 3D device, skipping test.\n");
7538 DestroyWindow(window);
7539 return;
7542 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
7543 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
7545 background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
7546 viewport = create_viewport(device, 0, 0, 640, 480);
7547 viewport_set_background(device, viewport, background);
7548 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
7549 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
7551 material = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
7552 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
7553 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
7555 hr = IDirect3DDevice2_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
7556 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
7557 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
7558 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
7559 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
7560 hr = IDirect3DDevice2_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
7561 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
7562 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
7563 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, 0);
7564 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
7565 hr = IDirect3DDevice2_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
7566 ok(SUCCEEDED(hr), "Failed to get light state, hr %#x.\n", hr);
7567 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
7569 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7571 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
7572 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7574 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, test_data[i].material ? mat_handle : 0);
7575 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
7577 hr = IDirect3DDevice2_BeginScene(device);
7578 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7579 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_VERTEX, quad, 4, 0);
7580 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7581 hr = IDirect3DDevice2_EndScene(device);
7582 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7583 color = get_surface_color(rt, 320, 240);
7584 ok(compare_color(color, test_data[i].expected_color, 1),
7585 "Got unexpected color 0x%08x, test %u.\n", color, i);
7588 destroy_material(material);
7589 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
7590 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
7591 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
7593 hr = IDirect3DViewport2_SetBackground(viewport, mat_handle);
7594 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
7595 hr = IDirect3DViewport2_GetBackground(viewport, &tmp, &valid);
7596 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
7597 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
7598 ok(valid, "Got unexpected valid %#x.\n", valid);
7599 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7600 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7601 color = get_surface_color(rt, 320, 240);
7602 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
7604 hr = IDirect3DViewport2_SetBackground(viewport, 0);
7605 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7606 hr = IDirect3DViewport2_GetBackground(viewport, &tmp, &valid);
7607 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
7608 ok(tmp == mat_handle, "Got unexpected material handle %#x, expected %#x.\n", tmp, mat_handle);
7609 ok(valid, "Got unexpected valid %#x.\n", valid);
7610 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7611 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7612 color = get_surface_color(rt, 320, 240);
7613 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
7615 destroy_viewport(device, viewport);
7616 viewport = create_viewport(device, 0, 0, 640, 480);
7618 hr = IDirect3DViewport2_GetBackground(viewport, &tmp, &valid);
7619 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#x.\n", hr);
7620 ok(!tmp, "Got unexpected material handle %#x.\n", tmp);
7621 ok(!valid, "Got unexpected valid %#x.\n", valid);
7622 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7623 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7624 color = get_surface_color(rt, 320, 240);
7625 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x.\n", color);
7627 destroy_viewport(device, viewport);
7628 destroy_material(background);
7629 destroy_material(material);
7630 IDirectDrawSurface_Release(rt);
7631 refcount = IDirect3DDevice2_Release(device);
7632 ok(!refcount, "Device has %u references left.\n", refcount);
7633 refcount = IDirectDraw2_Release(ddraw);
7634 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
7635 DestroyWindow(window);
7638 static void test_lighting(void)
7640 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
7641 static D3DMATRIX mat =
7643 1.0f, 0.0f, 0.0f, 0.0f,
7644 0.0f, 1.0f, 0.0f, 0.0f,
7645 0.0f, 0.0f, 1.0f, 0.0f,
7646 0.0f, 0.0f, 0.0f, 1.0f,
7648 mat_singular =
7650 1.0f, 0.0f, 1.0f, 0.0f,
7651 0.0f, 1.0f, 0.0f, 0.0f,
7652 1.0f, 0.0f, 1.0f, 0.0f,
7653 0.0f, 0.0f, 0.5f, 1.0f,
7655 mat_transf =
7657 0.0f, 0.0f, 1.0f, 0.0f,
7658 0.0f, 1.0f, 0.0f, 0.0f,
7659 -1.0f, 0.0f, 0.0f, 0.0f,
7660 10.f, 10.0f, 10.0f, 1.0f,
7662 mat_nonaffine =
7664 1.0f, 0.0f, 0.0f, 0.0f,
7665 0.0f, 1.0f, 0.0f, 0.0f,
7666 0.0f, 0.0f, 1.0f, -1.0f,
7667 10.f, 10.0f, 10.0f, 0.0f,
7669 static D3DLVERTEX unlitquad[] =
7671 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
7672 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
7673 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
7674 {{ 0.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
7676 litquad[] =
7678 {{-1.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
7679 {{-1.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
7680 {{ 0.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
7681 {{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
7683 static D3DVERTEX unlitnquad[] =
7685 {{0.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7686 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7687 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7688 {{1.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7690 litnquad[] =
7692 {{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7693 {{0.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7694 {{1.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7695 {{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
7697 nquad[] =
7699 {{-1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7700 {{-1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7701 {{ 1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7702 {{ 1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7704 rotatedquad[] =
7706 {{-10.0f}, {-11.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
7707 {{-10.0f}, { -9.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
7708 {{-10.0f}, { -9.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
7709 {{-10.0f}, {-11.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
7711 translatedquad[] =
7713 {{-11.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7714 {{-11.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7715 {{ -9.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7716 {{ -9.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
7718 static WORD indices[] = {0, 1, 2, 2, 3, 0};
7719 static const struct
7721 D3DMATRIX *world_matrix;
7722 void *quad;
7723 DWORD expected;
7724 const char *message;
7726 tests[] =
7728 {&mat, nquad, 0x000060ff, "Lit quad with light"},
7729 {&mat_singular, nquad, 0x00004db4, "Lit quad with singular world matrix"},
7730 {&mat_transf, rotatedquad, 0x000060ff, "Lit quad with transformation matrix"},
7731 {&mat_nonaffine, translatedquad, 0x000060ff, "Lit quad with non-affine matrix"},
7734 IDirect3DViewport2 *viewport, *viewport2;
7735 D3DMATERIALHANDLE mat_handle;
7736 IDirect3DMaterial2 *material;
7737 IDirect3DDevice2 *device;
7738 IDirectDrawSurface *rt;
7739 IDirect3DLight *light;
7740 D3DLIGHT2 light_desc;
7741 IDirectDraw2 *ddraw;
7742 IDirect3D2 *d3d;
7743 D3DCOLOR color;
7744 ULONG refcount;
7745 unsigned int i;
7746 HWND window;
7747 HRESULT hr;
7749 window = create_window();
7750 ddraw = create_ddraw();
7751 ok(!!ddraw, "Failed to create a ddraw object.\n");
7752 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
7754 skip("Failed to create a 3D device, skipping test.\n");
7755 DestroyWindow(window);
7756 return;
7759 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
7760 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7762 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
7763 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7765 viewport = create_viewport(device, 0, 0, 640, 480);
7766 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
7767 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7769 material = create_diffuse_and_ambient_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
7770 viewport_set_background(device, viewport, material);
7772 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7773 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7775 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
7776 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
7777 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
7778 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
7779 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
7780 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
7781 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
7782 ok(SUCCEEDED(hr), "Failed to disable zbuffer, hr %#x.\n", hr);
7783 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
7784 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
7785 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
7786 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
7788 hr = IDirect3DDevice2_BeginScene(device);
7789 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7791 /* There is no D3DRENDERSTATE_LIGHTING on ddraw < 7. */
7792 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
7793 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
7794 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_LVERTEX, unlitquad,
7795 4, indices, 6, 0);
7796 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7798 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
7799 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
7800 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_LVERTEX, litquad,
7801 4, indices, 6, 0);
7802 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7804 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
7805 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
7806 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, unlitnquad,
7807 4, indices, 6, 0);
7808 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7810 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
7811 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
7812 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, litnquad,
7813 4, indices, 6, 0);
7814 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7816 hr = IDirect3DDevice2_EndScene(device);
7817 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7819 color = get_surface_color(rt, 160, 360);
7820 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
7821 color = get_surface_color(rt, 160, 120);
7822 ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
7823 color = get_surface_color(rt, 480, 360);
7824 ok(color == 0x00ffffff, "Unlit quad with normals has color 0x%08x.\n", color);
7825 color = get_surface_color(rt, 480, 120);
7826 ok(color == 0x00ffffff, "Lit quad with normals has color 0x%08x.\n", color);
7828 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
7829 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7830 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
7831 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7832 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_AMBIENT, 0xff002000);
7833 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7835 hr = IDirect3D2_CreateLight(d3d, &light, NULL);
7836 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7837 memset(&light_desc, 0, sizeof(light_desc));
7838 light_desc.dwSize = sizeof(light_desc);
7839 light_desc.dltType = D3DLIGHT_DIRECTIONAL;
7840 U1(light_desc.dcvColor).r = 0.0f;
7841 U2(light_desc.dcvColor).g = 0.25f;
7842 U3(light_desc.dcvColor).b = 1.0f;
7843 U4(light_desc.dcvColor).a = 1.0f;
7844 U3(light_desc.dvDirection).z = 1.0f;
7845 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
7846 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7847 hr = IDirect3DViewport2_AddLight(viewport, light);
7848 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7849 hr = IDirect3DViewport2_AddLight(viewport, light);
7850 ok(hr == D3DERR_LIGHTHASVIEWPORT, "Got unexpected hr %#x.\n", hr);
7852 viewport2 = create_viewport(device, 0, 0, 640, 480);
7853 hr = IDirect3DViewport2_AddLight(viewport2, light);
7854 ok(hr == D3DERR_LIGHTHASVIEWPORT, "Got unexpected hr %#x.\n", hr);
7855 destroy_viewport(device, viewport2);
7857 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7858 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7860 hr = IDirect3DDevice2_BeginScene(device);
7861 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7863 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, nquad,
7864 4, indices, 6, 0);
7865 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7867 hr = IDirect3DDevice2_EndScene(device);
7868 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7870 color = get_surface_color(rt, 320, 240);
7871 ok(color == 0x00002000, "Lit quad with no light has color 0x%08x.\n", color);
7873 light_desc.dwFlags = D3DLIGHT_ACTIVE;
7874 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
7875 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7876 hr = IDirect3DViewport2_DeleteLight(viewport, light);
7877 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7878 light_desc.dwFlags = 0;
7879 hr = IDirect3DLight_GetLight(light, (D3DLIGHT *)&light_desc);
7880 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7881 ok(light_desc.dwFlags == D3DLIGHT_ACTIVE, "Got unexpected flags %#x.\n", light_desc.dwFlags);
7883 hr = IDirect3DViewport2_AddLight(viewport, light);
7884 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7885 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7887 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
7888 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
7890 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
7891 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
7893 hr = IDirect3DDevice2_BeginScene(device);
7894 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
7896 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX,
7897 tests[i].quad, 4, indices, 6, 0);
7898 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7900 hr = IDirect3DDevice2_EndScene(device);
7901 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
7903 color = get_surface_color(rt, 320, 240);
7904 ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
7907 hr = IDirect3DViewport2_DeleteLight(viewport, light);
7908 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
7909 IDirect3DLight_Release(light);
7910 destroy_material(material);
7911 destroy_viewport(device, viewport);
7912 IDirectDrawSurface2_Release(rt);
7913 refcount = IDirect3DDevice2_Release(device);
7914 ok(!refcount, "Device has %u references left.\n", refcount);
7915 IDirect3D2_Release(d3d);
7916 refcount = IDirectDraw2_Release(ddraw);
7917 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
7918 DestroyWindow(window);
7921 static void test_specular_lighting(void)
7923 static const unsigned int vertices_side = 5;
7924 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
7925 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
7926 static D3DMATRIX mat =
7928 1.0f, 0.0f, 0.0f, 0.0f,
7929 0.0f, 1.0f, 0.0f, 0.0f,
7930 0.0f, 0.0f, 1.0f, 0.0f,
7931 0.0f, 0.0f, 0.0f, 1.0f,
7933 static D3DLIGHT2 directional =
7935 sizeof(D3DLIGHT2),
7936 D3DLIGHT_DIRECTIONAL,
7937 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7938 {{0.0f}, {0.0f}, {0.0f}},
7939 {{0.0f}, {0.0f}, {1.0f}},
7941 point =
7943 sizeof(D3DLIGHT2),
7944 D3DLIGHT_POINT,
7945 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7946 {{0.0f}, {0.0f}, {0.0f}},
7947 {{0.0f}, {0.0f}, {0.0f}},
7948 100.0f,
7949 0.0f,
7950 0.0f, 0.0f, 1.0f,
7952 spot =
7954 sizeof(D3DLIGHT2),
7955 D3DLIGHT_SPOT,
7956 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7957 {{0.0f}, {0.0f}, {0.0f}},
7958 {{0.0f}, {0.0f}, {1.0f}},
7959 100.0f,
7960 1.0f,
7961 0.0f, 0.0f, 1.0f,
7962 M_PI / 12.0f, M_PI / 3.0f
7964 parallelpoint =
7966 sizeof(D3DLIGHT2),
7967 D3DLIGHT_PARALLELPOINT,
7968 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7969 {{0.5f}, {0.0f}, {-1.0f}},
7970 {{0.0f}, {0.0f}, {0.0f}},
7972 point_side =
7974 sizeof(D3DLIGHT2),
7975 D3DLIGHT_POINT,
7976 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7977 {{-1.1f}, {0.0f}, {1.1f}},
7978 {{0.0f}, {0.0f}, {0.0f}},
7979 100.0f,
7980 0.0f,
7981 1.0f, 0.0f, 0.0f,
7983 point_far =
7985 sizeof(D3DLIGHT2),
7986 D3DLIGHT_POINT,
7987 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
7988 {{0.0f}, {0.0f}, {0.1f}},
7989 {{0.0f}, {0.0f}, {0.0f}},
7990 1.0f,
7991 0.0f,
7992 1.0f, 0.0f, 0.0f,
7994 static const struct expected_color
7996 unsigned int x, y;
7997 D3DCOLOR color;
7999 expected_directional_local[] =
8001 {160, 120, 0x003c3c3c},
8002 {320, 120, 0x00717171},
8003 {480, 120, 0x003c3c3c},
8004 {160, 240, 0x00717171},
8005 {320, 240, 0x00ffffff},
8006 {480, 240, 0x00717171},
8007 {160, 360, 0x003c3c3c},
8008 {320, 360, 0x00717171},
8009 {480, 360, 0x003c3c3c},
8011 expected_point_local[] =
8013 {160, 120, 0x00000000},
8014 {320, 120, 0x00090909},
8015 {480, 120, 0x00000000},
8016 {160, 240, 0x00090909},
8017 {320, 240, 0x00fafafa},
8018 {480, 240, 0x00090909},
8019 {160, 360, 0x00000000},
8020 {320, 360, 0x00090909},
8021 {480, 360, 0x00000000},
8023 expected_spot_local[] =
8025 {160, 120, 0x00000000},
8026 {320, 120, 0x00020202},
8027 {480, 120, 0x00000000},
8028 {160, 240, 0x00020202},
8029 {320, 240, 0x00fafafa},
8030 {480, 240, 0x00020202},
8031 {160, 360, 0x00000000},
8032 {320, 360, 0x00020202},
8033 {480, 360, 0x00000000},
8035 expected_parallelpoint[] =
8037 {160, 120, 0x00050505},
8038 {320, 120, 0x002c2c2c},
8039 {480, 120, 0x006e6e6e},
8040 {160, 240, 0x00090909},
8041 {320, 240, 0x00717171},
8042 {480, 240, 0x00ffffff},
8043 {160, 360, 0x00050505},
8044 {320, 360, 0x002c2c2c},
8045 {480, 360, 0x006e6e6e},
8047 expected_point_far[] =
8049 {160, 120, 0x00000000},
8050 {320, 120, 0x00000000},
8051 {480, 120, 0x00000000},
8052 {160, 240, 0x00000000},
8053 {320, 240, 0x00ffffff},
8054 {480, 240, 0x00000000},
8055 {160, 360, 0x00000000},
8056 {320, 360, 0x00000000},
8057 {480, 360, 0x00000000},
8059 expected_zero[] =
8061 {160, 120, 0x00000000},
8062 {320, 120, 0x00000000},
8063 {480, 120, 0x00000000},
8064 {160, 240, 0x00000000},
8065 {320, 240, 0x00000000},
8066 {480, 240, 0x00000000},
8067 {160, 360, 0x00000000},
8068 {320, 360, 0x00000000},
8069 {480, 360, 0x00000000},
8071 static const struct
8073 D3DLIGHT2 *light;
8074 float specular_power;
8075 const struct expected_color *expected;
8076 unsigned int expected_count;
8078 tests[] =
8080 {&directional, 30.0f, expected_directional_local, ARRAY_SIZE(expected_directional_local)},
8081 {&point, 30.0f, expected_point_local, ARRAY_SIZE(expected_point_local)},
8082 {&spot, 30.0f, expected_spot_local, ARRAY_SIZE(expected_spot_local)},
8083 {&parallelpoint, 30.0f, expected_parallelpoint, ARRAY_SIZE(expected_parallelpoint)},
8084 {&point_side, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
8085 {&point_far, 1.0f, expected_point_far, ARRAY_SIZE(expected_point_far)},
8086 {&directional, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
8087 {&point, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
8088 {&spot, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
8089 {&parallelpoint, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
8090 {&point_far, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
8092 IDirect3D2 *d3d;
8093 IDirect3DDevice2 *device;
8094 IDirectDraw2 *ddraw;
8095 IDirectDrawSurface *rt;
8096 IDirect3DViewport2 *viewport;
8097 IDirect3DMaterial2 *material, *background_material;
8098 IDirect3DLight *light;
8099 D3DMATERIALHANDLE mat_handle;
8100 D3DCOLOR color;
8101 ULONG refcount;
8102 HWND window;
8103 HRESULT hr;
8104 unsigned int i, j, x, y;
8105 D3DVERTEX *quad;
8106 WORD *indices;
8108 window = create_window();
8109 ddraw = create_ddraw();
8110 ok(!!ddraw, "Failed to create a ddraw object.\n");
8111 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
8113 skip("Failed to create a 3D device, skipping test.\n");
8114 DestroyWindow(window);
8115 return;
8118 quad = HeapAlloc(GetProcessHeap(), 0, vertices_side * vertices_side * sizeof(*quad));
8119 indices = HeapAlloc(GetProcessHeap(), 0, indices_count * sizeof(*indices));
8120 for (i = 0, y = 0; y < vertices_side; ++y)
8122 for (x = 0; x < vertices_side; ++x)
8124 U1(quad[i]).x = x * 2.0f / (vertices_side - 1) - 1.0f;
8125 U2(quad[i]).y = y * 2.0f / (vertices_side - 1) - 1.0f;
8126 U3(quad[i]).z = 1.0f;
8127 U4(quad[i]).nx = 0.0f;
8128 U5(quad[i]).ny = 0.0f;
8129 U6(quad[i]).nz = -1.0f;
8130 U7(quad[i]).tu = 0.0f;
8131 U8(quad[i++]).tv = 0.0f;
8134 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
8136 for (x = 0; x < (vertices_side - 1); ++x)
8138 indices[i++] = y * vertices_side + x + 1;
8139 indices[i++] = y * vertices_side + x;
8140 indices[i++] = (y + 1) * vertices_side + x;
8141 indices[i++] = y * vertices_side + x + 1;
8142 indices[i++] = (y + 1) * vertices_side + x;
8143 indices[i++] = (y + 1) * vertices_side + x + 1;
8147 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
8148 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
8150 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
8151 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8153 viewport = create_viewport(device, 0, 0, 640, 480);
8154 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
8155 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
8157 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
8158 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
8159 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
8160 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
8161 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
8162 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
8163 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
8164 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
8165 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
8166 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
8168 background_material = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
8169 viewport_set_background(device, viewport, background_material);
8171 hr = IDirect3D2_CreateLight(d3d, &light, NULL);
8172 ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
8173 hr = IDirect3DViewport2_AddLight(viewport, light);
8174 ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
8176 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
8177 ok(SUCCEEDED(hr), "Failed to enable specular lighting, hr %#x.\n", hr);
8179 for (i = 0; i < ARRAY_SIZE(tests); ++i)
8181 tests[i].light->dwFlags = D3DLIGHT_ACTIVE;
8182 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)tests[i].light);
8183 ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
8185 material = create_specular_material(device, 1.0f, 1.0f, 1.0f, 1.0f, tests[i].specular_power);
8186 hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
8187 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
8188 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
8189 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
8191 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
8192 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
8194 hr = IDirect3DDevice2_BeginScene(device);
8195 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8197 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX,
8198 quad, vertices_side * vertices_side, indices, indices_count, 0);
8199 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8201 hr = IDirect3DDevice2_EndScene(device);
8202 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8204 for (j = 0; j < tests[i].expected_count; ++j)
8206 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
8207 ok(compare_color(color, tests[i].expected[j].color, 1),
8208 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
8209 tests[i].expected[j].color, tests[i].expected[j].x,
8210 tests[i].expected[j].y, color, i);
8213 destroy_material(material);
8216 hr = IDirect3DViewport2_DeleteLight(viewport, light);
8217 ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
8218 IDirect3DLight_Release(light);
8219 destroy_material(background_material);
8220 destroy_viewport(device, viewport);
8221 IDirectDrawSurface2_Release(rt);
8222 refcount = IDirect3DDevice2_Release(device);
8223 ok(!refcount, "Device has %u references left.\n", refcount);
8224 IDirect3D2_Release(d3d);
8225 refcount = IDirectDraw2_Release(ddraw);
8226 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
8227 DestroyWindow(window);
8228 HeapFree(GetProcessHeap(), 0, indices);
8229 HeapFree(GetProcessHeap(), 0, quad);
8232 static void test_palette_gdi(void)
8234 IDirectDrawSurface *surface, *primary;
8235 DDSURFACEDESC surface_desc;
8236 IDirectDraw2 *ddraw;
8237 IDirectDrawPalette *palette, *palette2;
8238 ULONG refcount;
8239 HWND window;
8240 HRESULT hr;
8241 PALETTEENTRY palette_entries[256];
8242 UINT i;
8243 HDC dc;
8244 DDBLTFX fx;
8245 RECT r;
8246 COLORREF color;
8247 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
8248 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
8249 * not the point of this test. */
8250 static const RGBQUAD expected1[] =
8252 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8253 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
8255 static const RGBQUAD expected2[] =
8257 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8258 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
8260 static const RGBQUAD expected3[] =
8262 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
8263 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
8265 HPALETTE ddraw_palette_handle;
8266 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
8267 RGBQUAD rgbquad[255];
8268 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
8270 window = create_window();
8271 ddraw = create_ddraw();
8272 ok(!!ddraw, "Failed to create a ddraw object.\n");
8273 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8274 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8276 memset(&surface_desc, 0, sizeof(surface_desc));
8277 surface_desc.dwSize = sizeof(surface_desc);
8278 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8279 surface_desc.dwWidth = 16;
8280 surface_desc.dwHeight = 16;
8281 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8282 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
8283 surface_desc.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8284 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 8;
8285 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8286 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8288 /* Avoid colors from the Windows default palette. */
8289 memset(palette_entries, 0, sizeof(palette_entries));
8290 palette_entries[1].peRed = 0x01;
8291 palette_entries[2].peGreen = 0x02;
8292 palette_entries[3].peBlue = 0x03;
8293 palette_entries[4].peRed = 0x13;
8294 palette_entries[4].peGreen = 0x14;
8295 palette_entries[4].peBlue = 0x15;
8296 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8297 palette_entries, &palette, NULL);
8298 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8300 /* If there is no palette assigned and the display mode is not 8 bpp, some
8301 * drivers refuse to create a DC while others allow it. If a DC is created,
8302 * the DIB color table is uninitialized and contains random colors. No error
8303 * is generated when trying to read pixels and random garbage is returned.
8305 * The most likely explanation is that if the driver creates a DC, it (or
8306 * the higher-level runtime) uses GetSystemPaletteEntries to find the
8307 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
8308 * contains uninitialized garbage. See comments below for the P8 case. */
8310 hr = IDirectDrawSurface_SetPalette(surface, palette);
8311 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8312 hr = IDirectDrawSurface_GetDC(surface, &dc);
8313 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8314 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8315 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8316 "Got unexpected palette %p, expected %p.\n",
8317 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8319 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8320 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8321 for (i = 0; i < ARRAY_SIZE(expected1); i++)
8323 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
8324 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8325 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8326 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
8328 for (; i < ARRAY_SIZE(rgbquad); i++)
8330 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8331 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8332 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8335 /* Update the palette while the DC is in use. This does not modify the DC. */
8336 palette_entries[4].peRed = 0x23;
8337 palette_entries[4].peGreen = 0x24;
8338 palette_entries[4].peBlue = 0x25;
8339 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
8340 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8342 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8343 ok(i == 1, "Expected count 1, got %u.\n", i);
8344 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8345 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8346 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8347 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8349 /* Neither does re-setting the palette. */
8350 hr = IDirectDrawSurface_SetPalette(surface, NULL);
8351 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8352 hr = IDirectDrawSurface_SetPalette(surface, palette);
8353 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8355 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8356 ok(i == 1, "Expected count 1, got %u.\n", i);
8357 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8358 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8359 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8360 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8362 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8363 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8365 /* Refresh the DC. This updates the palette. */
8366 hr = IDirectDrawSurface_GetDC(surface, &dc);
8367 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8368 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8369 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8370 for (i = 0; i < ARRAY_SIZE(expected2); i++)
8372 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8373 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8374 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8375 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8377 for (; i < ARRAY_SIZE(rgbquad); i++)
8379 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8380 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8381 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8383 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8384 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8386 refcount = IDirectDrawSurface_Release(surface);
8387 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8389 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
8390 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8391 if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8393 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8394 IDirectDrawPalette_Release(palette);
8395 IDirectDraw2_Release(ddraw);
8396 DestroyWindow(window);
8397 return;
8399 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
8401 memset(&surface_desc, 0, sizeof(surface_desc));
8402 surface_desc.dwSize = sizeof(surface_desc);
8403 surface_desc.dwFlags = DDSD_CAPS;
8404 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8405 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8406 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8408 memset(&fx, 0, sizeof(fx));
8409 fx.dwSize = sizeof(fx);
8410 U5(fx).dwFillColor = 3;
8411 SetRect(&r, 0, 0, 319, 479);
8412 hr = IDirectDrawSurface_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8413 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8414 SetRect(&r, 320, 0, 639, 479);
8415 U5(fx).dwFillColor = 4;
8416 hr = IDirectDrawSurface_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8417 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8419 hr = IDirectDrawSurface_SetPalette(primary, palette);
8420 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8421 hr = IDirectDrawSurface_GetDC(primary, &dc);
8422 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8424 color = GetPixel(dc, 160, 240);
8425 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
8426 color = GetPixel(dc, 480, 240);
8427 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
8429 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8430 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8431 "Got unexpected palette %p, expected %p.\n",
8432 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8433 SelectPalette(dc, ddraw_palette_handle, FALSE);
8435 /* The primary uses the system palette. In exclusive mode, the system palette matches
8436 * the ddraw palette attached to the primary, so the result is what you would expect
8437 * from a regular surface. Tests for the interaction between the ddraw palette and
8438 * the system palette are not included pending an application that depends on this.
8439 * The relation between those causes problems on Windows Vista and newer for games
8440 * like Age of Empires or StarCraft. Don't emulate it without a real need. */
8441 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8442 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8443 for (i = 0; i < ARRAY_SIZE(expected2); i++)
8445 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8446 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8447 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8448 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8450 for (; i < ARRAY_SIZE(rgbquad); i++)
8452 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8453 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8454 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8456 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
8457 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8459 memset(&surface_desc, 0, sizeof(surface_desc));
8460 surface_desc.dwSize = sizeof(surface_desc);
8461 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8462 surface_desc.dwWidth = 16;
8463 surface_desc.dwHeight = 16;
8464 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8465 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8466 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8468 /* Here the offscreen surface appears to use the primary's palette,
8469 * but in all likelihood it is actually the system palette. */
8470 hr = IDirectDrawSurface_GetDC(surface, &dc);
8471 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8472 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8473 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8474 for (i = 0; i < ARRAY_SIZE(expected2); i++)
8476 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8477 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8478 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8479 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8481 for (; i < ARRAY_SIZE(rgbquad); i++)
8483 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8484 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8485 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8487 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8488 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8490 /* On real hardware a change to the primary surface's palette applies immediately,
8491 * even on device contexts from offscreen surfaces that do not have their own
8492 * palette. On the testbot VMs this is not the case. Don't test this until we
8493 * know of an application that depends on this. */
8495 memset(palette_entries, 0, sizeof(palette_entries));
8496 palette_entries[1].peBlue = 0x40;
8497 palette_entries[2].peRed = 0x40;
8498 palette_entries[3].peGreen = 0x40;
8499 palette_entries[4].peRed = 0x12;
8500 palette_entries[4].peGreen = 0x34;
8501 palette_entries[4].peBlue = 0x56;
8502 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8503 palette_entries, &palette2, NULL);
8504 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8505 hr = IDirectDrawSurface_SetPalette(surface, palette2);
8506 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8508 /* A palette assigned to the offscreen surface overrides the primary / system
8509 * palette. */
8510 hr = IDirectDrawSurface_GetDC(surface, &dc);
8511 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8512 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8513 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8514 for (i = 0; i < ARRAY_SIZE(expected3); i++)
8516 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
8517 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8518 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8519 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
8521 for (; i < ARRAY_SIZE(rgbquad); i++)
8523 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8524 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8525 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8527 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
8528 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8530 refcount = IDirectDrawSurface_Release(surface);
8531 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8533 /* The Windows 8 testbot keeps extra references to the primary and
8534 * backbuffer while in 8 bpp mode. */
8535 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
8536 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8538 refcount = IDirectDrawSurface_Release(primary);
8539 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8540 refcount = IDirectDrawPalette_Release(palette2);
8541 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8542 refcount = IDirectDrawPalette_Release(palette);
8543 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8544 refcount = IDirectDraw2_Release(ddraw);
8545 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8546 DestroyWindow(window);
8549 static void test_palette_alpha(void)
8551 IDirectDrawSurface *surface1;
8552 IDirectDrawSurface2 *surface;
8553 DDSURFACEDESC surface_desc;
8554 IDirectDraw2 *ddraw;
8555 IDirectDrawPalette *palette;
8556 ULONG refcount;
8557 HWND window;
8558 HRESULT hr;
8559 PALETTEENTRY palette_entries[256];
8560 unsigned int i;
8561 static const struct
8563 DWORD caps, flags;
8564 BOOL attach_allowed;
8565 const char *name;
8567 test_data[] =
8569 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
8570 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
8571 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
8574 window = create_window();
8575 ddraw = create_ddraw();
8576 ok(!!ddraw, "Failed to create a ddraw object.\n");
8577 if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8579 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8580 IDirectDraw2_Release(ddraw);
8581 DestroyWindow(window);
8582 return;
8584 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8585 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8587 memset(palette_entries, 0, sizeof(palette_entries));
8588 palette_entries[1].peFlags = 0x42;
8589 palette_entries[2].peFlags = 0xff;
8590 palette_entries[3].peFlags = 0x80;
8591 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
8592 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8594 memset(palette_entries, 0x66, sizeof(palette_entries));
8595 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8596 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8597 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8598 palette_entries[0].peFlags);
8599 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8600 palette_entries[1].peFlags);
8601 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8602 palette_entries[2].peFlags);
8603 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8604 palette_entries[3].peFlags);
8606 IDirectDrawPalette_Release(palette);
8608 memset(palette_entries, 0, sizeof(palette_entries));
8609 palette_entries[1].peFlags = 0x42;
8610 palette_entries[1].peRed = 0xff;
8611 palette_entries[2].peFlags = 0xff;
8612 palette_entries[3].peFlags = 0x80;
8613 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
8614 palette_entries, &palette, NULL);
8615 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8617 memset(palette_entries, 0x66, sizeof(palette_entries));
8618 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8619 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8620 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8621 palette_entries[0].peFlags);
8622 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8623 palette_entries[1].peFlags);
8624 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8625 palette_entries[2].peFlags);
8626 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8627 palette_entries[3].peFlags);
8629 for (i = 0; i < ARRAY_SIZE(test_data); i++)
8631 memset(&surface_desc, 0, sizeof(surface_desc));
8632 surface_desc.dwSize = sizeof(surface_desc);
8633 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
8634 surface_desc.dwWidth = 128;
8635 surface_desc.dwHeight = 128;
8636 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8637 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
8638 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
8639 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
8640 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#x.\n", hr);
8641 IDirectDrawSurface_Release(surface1);
8643 hr = IDirectDrawSurface2_SetPalette(surface, palette);
8644 if (test_data[i].attach_allowed)
8645 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
8646 else
8647 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
8649 if (SUCCEEDED(hr))
8651 HDC dc;
8652 RGBQUAD rgbquad;
8653 UINT retval;
8655 hr = IDirectDrawSurface2_GetDC(surface, &dc);
8656 ok(SUCCEEDED(hr) || broken(hr == DDERR_CANTCREATEDC) /* Win2k testbot */,
8657 "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
8658 if (SUCCEEDED(hr))
8660 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
8661 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
8662 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
8663 rgbquad.rgbRed, test_data[i].name);
8664 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
8665 rgbquad.rgbGreen, test_data[i].name);
8666 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
8667 rgbquad.rgbBlue, test_data[i].name);
8668 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
8669 rgbquad.rgbReserved, test_data[i].name);
8670 hr = IDirectDrawSurface2_ReleaseDC(surface, dc);
8671 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8674 IDirectDrawSurface2_Release(surface);
8677 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
8678 memset(&surface_desc, 0, sizeof(surface_desc));
8679 surface_desc.dwSize = sizeof(surface_desc);
8680 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8681 surface_desc.dwWidth = 128;
8682 surface_desc.dwHeight = 128;
8683 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8684 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
8685 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
8686 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
8687 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8688 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8689 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
8690 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
8691 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8692 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
8693 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#x.\n", hr);
8694 IDirectDrawSurface_Release(surface1);
8696 hr = IDirectDrawSurface2_SetPalette(surface, palette);
8697 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
8698 IDirectDrawSurface2_Release(surface);
8700 /* The Windows 8 testbot keeps extra references to the primary
8701 * while in 8 bpp mode. */
8702 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
8703 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8705 refcount = IDirectDrawPalette_Release(palette);
8706 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8707 refcount = IDirectDraw2_Release(ddraw);
8708 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8709 DestroyWindow(window);
8712 static void test_lost_device(void)
8714 IDirectDrawSurface *sysmem_surface, *vidmem_surface;
8715 IDirectDrawSurface *surface, *back_buffer;
8716 DDSURFACEDESC surface_desc;
8717 HWND window1, window2;
8718 IDirectDraw2 *ddraw;
8719 ULONG refcount;
8720 DDSCAPS caps;
8721 HRESULT hr;
8722 BOOL ret;
8724 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8725 0, 0, 640, 480, 0, 0, 0, 0);
8726 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8727 0, 0, 640, 480, 0, 0, 0, 0);
8728 ddraw = create_ddraw();
8729 ok(!!ddraw, "Failed to create a ddraw object.\n");
8730 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8731 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8733 memset(&surface_desc, 0, sizeof(surface_desc));
8734 surface_desc.dwSize = sizeof(surface_desc);
8735 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8736 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8737 surface_desc.dwBackBufferCount = 1;
8738 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8739 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8741 memset(&surface_desc, 0, sizeof(surface_desc));
8742 surface_desc.dwSize = sizeof(surface_desc);
8743 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8744 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
8745 surface_desc.dwWidth = 100;
8746 surface_desc.dwHeight = 100;
8747 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
8748 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8750 memset(&surface_desc, 0, sizeof(surface_desc));
8751 surface_desc.dwSize = sizeof(surface_desc);
8752 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8753 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
8754 surface_desc.dwWidth = 64;
8755 surface_desc.dwHeight = 64;
8756 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
8757 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
8758 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
8759 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8760 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8761 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
8762 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &surface_desc, &vidmem_surface, NULL)))
8764 skip("Failed to create video memory surface, skipping related tests.\n");
8765 vidmem_surface = NULL;
8768 hr = IDirectDrawSurface_IsLost(surface);
8769 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8770 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8771 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8772 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8773 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8774 if (vidmem_surface)
8776 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8777 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8780 ret = SetForegroundWindow(GetDesktopWindow());
8781 ok(ret, "Failed to set foreground window.\n");
8782 hr = IDirectDrawSurface_IsLost(surface);
8783 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8784 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8785 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8786 hr = IDirectDrawSurface_Restore(surface);
8787 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
8788 hr = IDirectDrawSurface_IsLost(surface);
8789 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8790 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8791 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8792 hr = IDirectDrawSurface_Restore(sysmem_surface);
8793 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8794 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8795 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8796 if (vidmem_surface)
8798 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8799 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8800 hr = IDirectDrawSurface_Restore(vidmem_surface);
8801 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
8802 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8803 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8806 ret = SetForegroundWindow(window1);
8807 ok(ret, "Failed to set foreground window.\n");
8808 hr = IDirectDrawSurface_IsLost(surface);
8809 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8810 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8811 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8812 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8813 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8814 if (vidmem_surface)
8816 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8817 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8820 hr = restore_surfaces(ddraw);
8821 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8822 hr = IDirectDrawSurface_IsLost(surface);
8823 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8824 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8825 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8826 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8827 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8828 if (vidmem_surface)
8830 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8831 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8834 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8835 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8836 hr = IDirectDrawSurface_IsLost(surface);
8837 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8838 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8839 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8840 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8841 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8842 if (vidmem_surface)
8844 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8845 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8848 /* Trying to restore the primary will crash, probably because flippable
8849 * surfaces can't exist in DDSCL_NORMAL. */
8850 IDirectDrawSurface_Release(surface);
8851 memset(&surface_desc, 0, sizeof(surface_desc));
8852 surface_desc.dwSize = sizeof(surface_desc);
8853 surface_desc.dwFlags = DDSD_CAPS;
8854 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8855 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8856 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8857 hr = restore_surfaces(ddraw);
8858 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8860 hr = IDirectDrawSurface_IsLost(surface);
8861 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8863 ret = SetForegroundWindow(GetDesktopWindow());
8864 ok(ret, "Failed to set foreground window.\n");
8865 hr = IDirectDrawSurface_IsLost(surface);
8866 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8867 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8868 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8869 if (vidmem_surface)
8871 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8872 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8875 ret = SetForegroundWindow(window1);
8876 ok(ret, "Failed to set foreground window.\n");
8877 hr = IDirectDrawSurface_IsLost(surface);
8878 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8879 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8880 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8881 if (vidmem_surface)
8883 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8884 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8887 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8888 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8889 hr = IDirectDrawSurface_IsLost(surface);
8890 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8891 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8892 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8893 if (vidmem_surface)
8895 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8896 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8899 hr = restore_surfaces(ddraw);
8900 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8901 hr = IDirectDrawSurface_IsLost(surface);
8902 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8903 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8904 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8905 if (vidmem_surface)
8907 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8908 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8911 IDirectDrawSurface_Release(surface);
8912 memset(&surface_desc, 0, sizeof(surface_desc));
8913 surface_desc.dwSize = sizeof(surface_desc);
8914 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8915 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8916 surface_desc.dwBackBufferCount = 1;
8917 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8918 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8920 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8921 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8922 hr = IDirectDrawSurface_IsLost(surface);
8923 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8924 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8925 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8926 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8927 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8928 if (vidmem_surface)
8930 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8931 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8934 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8935 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8936 hr = IDirectDrawSurface_IsLost(surface);
8937 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8938 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8939 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8940 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8941 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8942 if (vidmem_surface)
8944 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8945 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8948 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8949 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8950 hr = IDirectDrawSurface_IsLost(surface);
8951 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8952 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8953 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8954 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8955 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8956 if (vidmem_surface)
8958 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8959 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8962 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
8963 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8964 hr = IDirectDrawSurface_IsLost(surface);
8965 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8966 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8967 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8968 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8969 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8970 if (vidmem_surface)
8972 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8973 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8976 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8977 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8978 hr = IDirectDrawSurface_IsLost(surface);
8979 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8980 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8981 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8982 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8983 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8984 if (vidmem_surface)
8986 hr = IDirectDrawSurface_IsLost(vidmem_surface);
8987 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8990 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8991 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8992 hr = IDirectDrawSurface_IsLost(surface);
8993 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8994 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
8995 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8996 hr = IDirectDrawSurface_IsLost(sysmem_surface);
8997 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8998 if (vidmem_surface)
9000 hr = IDirectDrawSurface_IsLost(vidmem_surface);
9001 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9004 memset(&caps, 0, sizeof(caps));
9005 caps.dwCaps = DDSCAPS_FLIP;
9007 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &back_buffer);
9008 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9009 hr = IDirectDrawSurface_Restore(surface);
9010 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9011 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &back_buffer);
9012 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9013 hr = IDirectDrawSurface_IsLost(back_buffer);
9014 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9015 IDirectDrawSurface_Release(back_buffer);
9017 if (vidmem_surface)
9018 IDirectDrawSurface_Release(vidmem_surface);
9019 IDirectDrawSurface_Release(sysmem_surface);
9020 IDirectDrawSurface_Release(surface);
9021 refcount = IDirectDraw2_Release(ddraw);
9022 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9023 DestroyWindow(window2);
9024 DestroyWindow(window1);
9027 static void test_surface_desc_lock(void)
9029 IDirectDrawSurface *surface;
9030 DDSURFACEDESC surface_desc;
9031 IDirectDraw2 *ddraw;
9032 ULONG refcount;
9033 HWND window;
9034 HRESULT hr;
9036 window = create_window();
9037 ddraw = create_ddraw();
9038 ok(!!ddraw, "Failed to create a ddraw object.\n");
9039 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9040 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9042 memset(&surface_desc, 0, sizeof(surface_desc));
9043 surface_desc.dwSize = sizeof(surface_desc);
9044 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
9045 surface_desc.dwWidth = 16;
9046 surface_desc.dwHeight = 16;
9047 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9048 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9049 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9051 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9052 surface_desc.dwSize = sizeof(surface_desc);
9053 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
9054 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9055 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9057 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9058 surface_desc.dwSize = sizeof(surface_desc);
9059 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, 0, NULL);
9060 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9061 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9062 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9063 surface_desc.dwSize = sizeof(surface_desc);
9064 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
9065 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9066 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9067 hr = IDirectDrawSurface_Unlock(surface, NULL);
9068 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9070 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9071 surface_desc.dwSize = sizeof(surface_desc);
9072 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
9073 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9074 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9076 IDirectDrawSurface_Release(surface);
9077 refcount = IDirectDraw2_Release(ddraw);
9078 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9079 DestroyWindow(window);
9082 static void test_texturemapblend(void)
9084 HRESULT hr;
9085 DDSURFACEDESC ddsd;
9086 DDBLTFX fx;
9087 static RECT rect = {0, 0, 64, 128};
9088 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9089 DDCOLORKEY ckey;
9090 IDirectDrawSurface *surface, *rt;
9091 IDirect3DTexture2 *texture;
9092 D3DTEXTUREHANDLE texture_handle;
9093 HWND window;
9094 IDirectDraw2 *ddraw;
9095 IDirect3DDevice2 *device;
9096 IDirect3DMaterial2 *material;
9097 IDirect3DViewport2 *viewport;
9098 ULONG ref;
9099 D3DCOLOR color;
9101 static D3DTLVERTEX test1_quads[] =
9103 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {0.0f}},
9104 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {0.0f}, {1.0f}},
9105 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {0.0f}},
9106 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0}, {1.0f}, {1.0f}},
9107 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {0.0f}},
9108 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {0.0f}, {1.0f}},
9109 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {0.0f}},
9110 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x80ffffff}, {0}, {1.0f}, {1.0f}},
9112 test2_quads[] =
9114 {{0.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {0.0f}},
9115 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {0.0f}, {1.0f}},
9116 {{640.0f}, {0.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {0.0f}},
9117 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x00ff0080}, {0}, {1.0f}, {1.0f}},
9118 {{0.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {0.0f}},
9119 {{0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {0.0f}, {1.0f}},
9120 {{640.0f}, {240.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {0.0f}},
9121 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x008000ff}, {0}, {1.0f}, {1.0f}},
9124 window = create_window();
9125 ddraw = create_ddraw();
9126 ok(!!ddraw, "Failed to create a ddraw object.\n");
9127 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
9129 skip("Failed to create a 3D device, skipping test.\n");
9130 DestroyWindow(window);
9131 IDirectDraw2_Release(ddraw);
9132 return;
9135 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
9136 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9138 material = create_diffuse_material(device, 0.0f, 0.0f, 0.0f, 1.0f);
9139 viewport = create_viewport(device, 0, 0, 640, 480);
9140 viewport_set_background(device, viewport, material);
9141 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
9142 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
9144 /* Test alpha with DDPF_ALPHAPIXELS texture - should be taken from texture alpha channel.
9146 * The vertex alpha is completely ignored in this case, so case 1 and 2 combined are not
9147 * a D3DTOP_MODULATE with texture alpha = 0xff in case 2 (no alpha in texture). */
9148 memset(&ddsd, 0, sizeof(ddsd));
9149 ddsd.dwSize = sizeof(ddsd);
9150 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9151 ddsd.dwHeight = 128;
9152 ddsd.dwWidth = 128;
9153 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9154 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
9155 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9156 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
9157 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9158 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9159 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
9160 U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
9161 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
9162 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9164 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9165 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9166 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
9167 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
9168 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
9169 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9171 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9172 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9174 memset(&fx, 0, sizeof(fx));
9175 fx.dwSize = sizeof(fx);
9176 U5(fx).dwFillColor = 0xff0000ff;
9177 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9178 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9179 U5(fx).dwFillColor = 0x800000ff;
9180 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9181 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9183 /* Note that the ddraw1 version of this test runs tests 1-3 with D3DRENDERSTATE_COLORKEYENABLE
9184 * enabled, whereas this version only runs test 4 with color keying on. Because no color key
9185 * is set on the texture this should not result in different behavior. */
9186 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
9187 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9188 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9189 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9190 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
9191 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9192 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
9193 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9194 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
9195 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9196 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
9197 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9199 hr = IDirect3DDevice2_BeginScene(device);
9200 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9201 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[0], 4, 0);
9202 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9203 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[4], 4, 0);
9204 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9205 hr = IDirect3DDevice2_EndScene(device);
9206 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9208 color = get_surface_color(rt, 5, 5);
9209 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9210 color = get_surface_color(rt, 400, 5);
9211 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9212 color = get_surface_color(rt, 5, 245);
9213 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9214 color = get_surface_color(rt, 400, 245);
9215 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9217 IDirect3DTexture2_Release(texture);
9218 ref = IDirectDrawSurface_Release(surface);
9219 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
9221 /* Test alpha with texture that has no alpha channel - alpha should be taken from diffuse vertex color. */
9222 memset(&ddsd, 0, sizeof(ddsd));
9223 ddsd.dwSize = sizeof(ddsd);
9224 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9225 ddsd.dwHeight = 128;
9226 ddsd.dwWidth = 128;
9227 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9228 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
9229 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
9230 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
9231 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9232 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9233 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
9235 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
9236 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9238 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9239 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9240 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
9241 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
9242 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
9243 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9245 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9246 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9248 U5(fx).dwFillColor = 0xff0000ff;
9249 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9250 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9251 U5(fx).dwFillColor = 0x800000ff;
9252 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9253 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9255 hr = IDirect3DDevice2_BeginScene(device);
9256 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9257 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[0], 4, 0);
9258 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9259 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[4], 4, 0);
9260 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9261 hr = IDirect3DDevice2_EndScene(device);
9262 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9264 color = get_surface_color(rt, 5, 5);
9265 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9266 color = get_surface_color(rt, 400, 5);
9267 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9268 color = get_surface_color(rt, 5, 245);
9269 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9270 color = get_surface_color(rt, 400, 245);
9271 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
9273 IDirect3DTexture2_Release(texture);
9274 ref = IDirectDrawSurface_Release(surface);
9275 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
9277 /* Test RGB - should multiply color components from diffuse vertex color and texture. */
9278 memset(&ddsd, 0, sizeof(ddsd));
9279 ddsd.dwSize = sizeof(ddsd);
9280 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9281 ddsd.dwHeight = 128;
9282 ddsd.dwWidth = 128;
9283 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9284 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
9285 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9286 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
9287 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9288 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9289 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
9290 U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
9291 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
9292 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9294 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9295 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9296 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
9297 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
9298 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
9299 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9301 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9302 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9304 U5(fx).dwFillColor = 0x00ffffff;
9305 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9306 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9307 U5(fx).dwFillColor = 0x00ffff80;
9308 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9309 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9311 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
9312 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9314 hr = IDirect3DDevice2_BeginScene(device);
9315 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9316 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test2_quads[0], 4, 0);
9317 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9318 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test2_quads[4], 4, 0);
9319 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9320 hr = IDirect3DDevice2_EndScene(device);
9321 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9323 color = get_surface_color(rt, 5, 5);
9324 ok(compare_color(color, 0x00ff0040, 2), "Got unexpected color 0x%08x.\n", color);
9325 color = get_surface_color(rt, 400, 5);
9326 ok(compare_color(color, 0x00ff0080, 2), "Got unexpected color 0x%08x.\n", color);
9327 color = get_surface_color(rt, 5, 245);
9328 ok(compare_color(color, 0x00800080, 2), "Got unexpected color 0x%08x.\n", color);
9329 color = get_surface_color(rt, 400, 245);
9330 ok(compare_color(color, 0x008000ff, 2), "Got unexpected color 0x%08x.\n", color);
9332 IDirect3DTexture2_Release(texture);
9333 ref = IDirectDrawSurface_Release(surface);
9334 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
9336 /* Test alpha again, now with color keyed texture (colorkey emulation in wine can interfere). */
9337 memset(&ddsd, 0, sizeof(ddsd));
9338 ddsd.dwSize = sizeof(ddsd);
9339 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
9340 ddsd.dwHeight = 128;
9341 ddsd.dwWidth = 128;
9342 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9343 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
9344 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
9345 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 16;
9346 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xf800;
9347 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x07e0;
9348 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x001f;
9350 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
9351 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9353 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
9354 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
9355 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
9356 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
9357 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
9358 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9360 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9361 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9363 U5(fx).dwFillColor = 0xf800;
9364 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9365 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9366 U5(fx).dwFillColor = 0x001f;
9367 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9368 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#x.\n", hr);
9370 ckey.dwColorSpaceLowValue = 0x001f;
9371 ckey.dwColorSpaceHighValue = 0x001f;
9372 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
9373 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
9375 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
9376 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9377 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
9378 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9380 hr = IDirect3DDevice2_BeginScene(device);
9381 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9382 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[0], 4, 0);
9383 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9384 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &test1_quads[4], 4, 0);
9385 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9386 hr = IDirect3DDevice2_EndScene(device);
9387 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9389 color = get_surface_color(rt, 5, 5);
9390 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
9391 color = get_surface_color(rt, 400, 5);
9392 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
9393 color = get_surface_color(rt, 5, 245);
9394 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
9395 color = get_surface_color(rt, 400, 245);
9396 ok(compare_color(color, 0x00800000, 2), "Got unexpected color 0x%08x.\n", color);
9398 IDirect3DTexture2_Release(texture);
9399 ref = IDirectDrawSurface_Release(surface);
9400 ok(ref == 0, "Surface not properly released, refcount %u.\n", ref);
9402 destroy_viewport(device, viewport);
9403 ref = IDirect3DMaterial2_Release(material);
9404 ok(ref == 0, "Material not properly released, refcount %u.\n", ref);
9405 IDirectDrawSurface_Release(rt);
9406 IDirect3DDevice2_Release(device);
9407 ref = IDirectDraw2_Release(ddraw);
9408 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
9409 DestroyWindow(window);
9412 static void test_viewport_clear_rect(void)
9414 HRESULT hr;
9415 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9416 static D3DRECT clear_rect2 = {{90}, {90}, {110}, {110}};
9417 IDirectDrawSurface *rt;
9418 HWND window;
9419 IDirectDraw2 *ddraw;
9420 IDirect3DDevice2 *device;
9421 IDirect3DMaterial2 *red, *green;
9422 IDirect3DViewport2 *viewport, *viewport2;
9423 ULONG ref;
9424 D3DCOLOR color;
9426 window = create_window();
9427 ddraw = create_ddraw();
9428 ok(!!ddraw, "Failed to create a ddraw object.\n");
9429 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
9431 skip("Failed to create a 3D device, skipping test.\n");
9432 DestroyWindow(window);
9433 IDirectDraw2_Release(ddraw);
9434 return;
9437 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
9438 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9440 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
9441 viewport = create_viewport(device, 0, 0, 640, 480);
9442 viewport_set_background(device, viewport, red);
9443 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9444 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
9446 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
9447 viewport2 = create_viewport(device, 100, 100, 20, 20);
9448 viewport_set_background(device, viewport2, green);
9449 hr = IDirect3DViewport2_Clear(viewport2, 1, &clear_rect2, D3DCLEAR_TARGET);
9450 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
9452 color = get_surface_color(rt, 85, 85); /* Outside both. */
9453 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
9454 color = get_surface_color(rt, 95, 95); /* Outside vp, inside rect. */
9455 /* AMD GPUs ignore the viewport dimensions and only care about the rectangle. */
9456 ok(compare_color(color, 0x00ff0000, 1) || broken(compare_color(color, 0x0000ff00, 1)),
9457 "Got unexpected color 0x%08x.\n", color);
9458 color = get_surface_color(rt, 105, 105); /* Inside both. */
9459 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
9460 color = get_surface_color(rt, 115, 115); /* Inside vp, outside rect. */
9461 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
9462 color = get_surface_color(rt, 125, 125); /* Outside both. */
9463 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
9465 destroy_viewport(device, viewport2);
9466 destroy_material(green);
9467 destroy_viewport(device, viewport);
9468 destroy_material(red);
9469 IDirectDrawSurface_Release(rt);
9470 IDirect3DDevice2_Release(device);
9471 ref = IDirectDraw2_Release(ddraw);
9472 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
9473 DestroyWindow(window);
9476 static void test_color_fill(void)
9478 HRESULT hr;
9479 IDirect3DDevice2 *device;
9480 IDirectDraw2 *ddraw;
9481 IDirectDrawSurface *surface, *surface2;
9482 DDSURFACEDESC surface_desc;
9483 ULONG refcount;
9484 BOOL is_warp;
9485 HWND window;
9486 unsigned int i;
9487 DDBLTFX fx;
9488 RECT rect = {5, 5, 7, 7};
9489 DWORD *color;
9490 DWORD num_fourcc_codes, *fourcc_codes;
9491 DDCAPS hal_caps;
9492 BOOL support_uyvy = FALSE, support_yuy2 = FALSE;
9493 static const struct
9495 DWORD caps;
9496 HRESULT colorfill_hr, depthfill_hr;
9497 BOOL rop_success;
9498 const char *name;
9499 DWORD result;
9500 BOOL check_result;
9501 DDPIXELFORMAT format;
9503 tests[] =
9506 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
9507 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
9509 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9510 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9514 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
9515 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
9517 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9518 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9522 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
9523 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
9525 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9526 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9530 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
9531 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
9533 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9534 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9538 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY,
9539 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0xdeadbeef, TRUE,
9540 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9543 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
9544 * different afterwards. DX9+ GPUs set one of the two luminance values
9545 * in each block, but AMD and Nvidia GPUs disagree on which luminance
9546 * value they set. r200 (dx8) just sets the entire block to the clear
9547 * value. */
9548 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
9549 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
9551 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9552 {0}, {0}, {0}, {0}, {0}
9556 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
9557 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
9559 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9560 {0}, {0}, {0}, {0}, {0}
9564 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
9565 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
9567 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9568 {0}, {0}, {0}, {0}, {0}
9572 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY,
9573 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
9575 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9576 {0}, {0}, {0}, {0}, {0}
9580 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
9581 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
9583 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9584 {0}, {0}, {0}, {0}, {0}
9588 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
9589 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
9591 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9592 {0}, {0}, {0}, {0}, {0}
9596 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
9597 * surface works, presumably because it is handled by the runtime instead of
9598 * the driver. */
9599 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
9600 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
9602 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9603 {8}, {0}, {0}, {0}, {0}
9607 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
9608 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
9610 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9611 {8}, {0}, {0}, {0}, {0}
9615 static const struct
9617 DWORD rop;
9618 const char *name;
9619 HRESULT hr;
9621 rops[] =
9623 {SRCCOPY, "SRCCOPY", DD_OK},
9624 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
9625 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
9626 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
9627 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
9628 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
9629 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
9630 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
9631 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
9632 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
9633 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
9634 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
9635 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
9636 {BLACKNESS, "BLACKNESS", DD_OK},
9637 {WHITENESS, "WHITENESS", DD_OK},
9638 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
9641 window = create_window();
9642 ddraw = create_ddraw();
9643 ok(!!ddraw, "Failed to create a ddraw object.\n");
9644 is_warp = ddraw_is_warp(ddraw);
9645 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
9647 skip("Failed to create a 3D device, skipping test.\n");
9648 DestroyWindow(window);
9649 IDirectDraw2_Release(ddraw);
9650 return;
9653 hr = IDirectDraw2_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
9654 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9655 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
9656 num_fourcc_codes * sizeof(*fourcc_codes));
9657 if (!fourcc_codes)
9658 goto done;
9659 hr = IDirectDraw2_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
9660 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9661 for (i = 0; i < num_fourcc_codes; i++)
9663 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
9664 support_yuy2 = TRUE;
9665 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
9666 support_uyvy = TRUE;
9668 HeapFree(GetProcessHeap(), 0, fourcc_codes);
9670 memset(&hal_caps, 0, sizeof(hal_caps));
9671 hal_caps.dwSize = sizeof(hal_caps);
9672 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
9673 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9675 if ((!support_yuy2 && !support_uyvy) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9676 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
9678 for (i = 0; i < ARRAY_SIZE(tests); i++)
9680 DWORD expected_broken = tests[i].result;
9681 DWORD mask = 0xffffffffu;
9683 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
9684 memset(&fx, 0, sizeof(fx));
9685 fx.dwSize = sizeof(fx);
9686 U5(fx).dwFillColor = 0xdeadbeef;
9688 memset(&surface_desc, 0, sizeof(surface_desc));
9689 surface_desc.dwSize = sizeof(surface_desc);
9690 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9691 surface_desc.dwWidth = 64;
9692 surface_desc.dwHeight = 64;
9693 surface_desc.ddpfPixelFormat = tests[i].format;
9694 surface_desc.ddsCaps.dwCaps = tests[i].caps;
9696 if (tests[i].caps & DDSCAPS_TEXTURE)
9698 struct format_support_check check = {&tests[i].format, FALSE};
9699 hr = IDirect3DDevice2_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
9700 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
9701 if (!check.supported)
9702 continue;
9705 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !support_yuy2)
9706 continue;
9707 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !support_uyvy)
9708 continue;
9709 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9710 continue;
9712 if (tests[i].caps & DDSCAPS_ZBUFFER)
9714 surface_desc.dwFlags &= ~DDSD_PIXELFORMAT;
9715 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
9716 U2(surface_desc).dwZBufferBitDepth = get_device_z_depth(device);
9717 mask >>= (32 - U2(surface_desc).dwZBufferBitDepth);
9718 /* Some drivers seem to convert depth values incorrectly or not at
9719 * all. Affects at least AMD PALM, 8.17.10.1247. */
9720 if (tests[i].caps & DDSCAPS_VIDEOMEMORY)
9722 DWORD expected;
9723 float f, g;
9725 expected = tests[i].result & mask;
9726 f = ceilf(logf(expected + 1.0f) / logf(2.0f));
9727 g = (f + 1.0f) / 2.0f;
9728 g -= (int)g;
9729 expected_broken = (expected / exp2f(f) - g) * 256;
9730 expected_broken *= 0x01010101;
9734 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9735 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
9737 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9738 todo_wine_if (tests[i].format.dwFourCC)
9739 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9740 hr, tests[i].colorfill_hr, tests[i].name);
9742 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9743 todo_wine_if (tests[i].format.dwFourCC)
9744 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9745 hr, tests[i].colorfill_hr, tests[i].name);
9747 if (SUCCEEDED(hr) && tests[i].check_result)
9749 memset(&surface_desc, 0, sizeof(surface_desc));
9750 surface_desc.dwSize = sizeof(surface_desc);
9751 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9752 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9753 color = surface_desc.lpSurface;
9754 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
9755 *color, tests[i].result, tests[i].name);
9756 hr = IDirectDrawSurface_Unlock(surface, NULL);
9757 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9760 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9761 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9762 hr, tests[i].depthfill_hr, tests[i].name);
9763 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9764 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9765 hr, tests[i].depthfill_hr, tests[i].name);
9767 if (SUCCEEDED(hr) && tests[i].check_result)
9769 memset(&surface_desc, 0, sizeof(surface_desc));
9770 surface_desc.dwSize = sizeof(surface_desc);
9771 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9772 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9773 color = surface_desc.lpSurface;
9774 todo_wine_if(tests[i].caps & DDSCAPS_VIDEOMEMORY && U2(surface_desc).dwZBufferBitDepth != 16)
9775 ok((*color & mask) == (tests[i].result & mask) || broken((*color & mask) == (expected_broken & mask))
9776 || broken(is_warp && (*color & mask) == (~0u & mask)) /* Windows 8+ testbot. */,
9777 "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
9778 *color & mask, tests[i].result & mask, tests[i].name);
9779 hr = IDirectDrawSurface_Unlock(surface, NULL);
9780 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9783 U5(fx).dwFillColor = 0xdeadbeef;
9784 fx.dwROP = BLACKNESS;
9785 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9786 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
9787 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9788 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
9789 U5(fx).dwFillColor, tests[i].name);
9791 if (SUCCEEDED(hr) && tests[i].check_result)
9793 memset(&surface_desc, 0, sizeof(surface_desc));
9794 surface_desc.dwSize = sizeof(surface_desc);
9795 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9796 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9797 color = surface_desc.lpSurface;
9798 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
9799 *color, tests[i].name);
9800 hr = IDirectDrawSurface_Unlock(surface, NULL);
9801 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9804 fx.dwROP = WHITENESS;
9805 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9806 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
9807 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9808 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
9809 U5(fx).dwFillColor, tests[i].name);
9811 if (SUCCEEDED(hr) && tests[i].check_result)
9813 memset(&surface_desc, 0, sizeof(surface_desc));
9814 surface_desc.dwSize = sizeof(surface_desc);
9815 hr = IDirectDrawSurface_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9816 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9817 color = surface_desc.lpSurface;
9818 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
9819 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
9820 *color, tests[i].name);
9821 hr = IDirectDrawSurface_Unlock(surface, NULL);
9822 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9825 IDirectDrawSurface_Release(surface);
9828 memset(&fx, 0, sizeof(fx));
9829 fx.dwSize = sizeof(fx);
9830 U5(fx).dwFillColor = 0xdeadbeef;
9831 fx.dwROP = WHITENESS;
9833 memset(&surface_desc, 0, sizeof(surface_desc));
9834 surface_desc.dwSize = sizeof(surface_desc);
9835 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9836 surface_desc.dwWidth = 64;
9837 surface_desc.dwHeight = 64;
9838 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
9839 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
9840 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
9841 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9842 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9843 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
9844 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
9845 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9846 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9847 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
9848 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9850 /* No DDBLTFX. */
9851 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
9852 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9853 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
9854 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9856 /* Unused source rectangle. */
9857 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9858 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9859 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9860 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9862 /* Unused source surface. */
9863 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9864 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9865 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9866 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9867 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9868 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9869 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9870 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9872 /* Inverted destination or source rectangle. */
9873 SetRect(&rect, 5, 7, 7, 5);
9874 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9875 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9876 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9877 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9878 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9879 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9880 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9881 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9882 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9883 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9885 /* Negative rectangle. */
9886 SetRect(&rect, -1, -1, 5, 5);
9887 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9888 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9889 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9890 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9891 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9892 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9893 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9894 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9895 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9896 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9898 /* Out of bounds rectangle. */
9899 SetRect(&rect, 0, 0, 65, 65);
9900 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9901 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9902 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9903 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9905 /* Combine multiple flags. */
9906 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9907 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9908 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
9909 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9910 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
9911 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9913 for (i = 0; i < ARRAY_SIZE(rops); i++)
9915 fx.dwROP = rops[i].rop;
9916 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9917 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
9920 IDirectDrawSurface_Release(surface2);
9921 IDirectDrawSurface_Release(surface);
9923 memset(&surface_desc, 0, sizeof(surface_desc));
9924 surface_desc.dwSize = sizeof(surface_desc);
9925 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
9926 surface_desc.dwWidth = 64;
9927 surface_desc.dwHeight = 64;
9928 U2(surface_desc).dwZBufferBitDepth = get_device_z_depth(device);
9929 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
9930 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9931 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9932 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
9933 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9935 /* No DDBLTFX. */
9936 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
9937 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9939 /* Unused source rectangle. */
9940 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9941 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9943 /* Unused source surface. */
9944 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9945 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9946 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9947 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9949 /* Inverted destination or source rectangle. */
9950 SetRect(&rect, 5, 7, 7, 5);
9951 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9952 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9953 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9954 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9955 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9956 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9957 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9958 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9960 /* Negative rectangle. */
9961 SetRect(&rect, -1, -1, 5, 5);
9962 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9963 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9964 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9965 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9966 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9967 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9968 hr = IDirectDrawSurface_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9969 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9971 /* Out of bounds rectangle. */
9972 SetRect(&rect, 0, 0, 65, 65);
9973 hr = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9974 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9976 /* Combine multiple flags. */
9977 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9978 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9980 IDirectDrawSurface_Release(surface2);
9981 IDirectDrawSurface_Release(surface);
9983 done:
9984 IDirect3DDevice2_Release(device);
9985 refcount = IDirectDraw2_Release(ddraw);
9986 ok(refcount == 0, "Ddraw object not properly released, refcount %u.\n", refcount);
9987 DestroyWindow(window);
9990 static void test_colorkey_precision(void)
9992 static D3DLVERTEX quad[] =
9994 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xff000000}, {0}, {0.0f}, {0.0f}},
9995 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff000000}, {0}, {0.0f}, {1.0f}},
9996 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff000000}, {0}, {1.0f}, {0.0f}},
9997 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xff000000}, {0}, {1.0f}, {1.0f}},
9999 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10000 IDirect3DDevice2 *device;
10001 IDirectDraw2 *ddraw;
10002 IDirectDrawSurface *rt;
10003 IDirect3DViewport2 *viewport;
10004 HWND window;
10005 HRESULT hr;
10006 IDirectDrawSurface *src, *dst, *texture;
10007 D3DTEXTUREHANDLE handle;
10008 IDirect3DTexture2 *d3d_texture;
10009 IDirect3DMaterial2 *green;
10010 DDSURFACEDESC surface_desc, lock_desc;
10011 ULONG refcount;
10012 D3DCOLOR color;
10013 unsigned int t, c;
10014 DDCOLORKEY ckey;
10015 DDBLTFX fx;
10016 DWORD data[4] = {0}, color_mask;
10017 BOOL is_nvidia, is_warp;
10018 static const struct
10020 unsigned int max, shift, bpp, clear;
10021 const char *name;
10022 BOOL skip_nv;
10023 DDPIXELFORMAT fmt;
10025 tests[] =
10028 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
10030 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10031 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
10036 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
10038 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10039 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10044 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
10046 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10047 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10052 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
10054 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10055 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
10060 window = create_window();
10061 ddraw = create_ddraw();
10062 ok(!!ddraw, "Failed to create a ddraw object.\n");
10063 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
10065 skip("Failed to create a 3D device, skipping test.\n");
10066 DestroyWindow(window);
10067 IDirectDraw2_Release(ddraw);
10068 return;
10070 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
10071 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10073 is_nvidia = ddraw_is_nvidia(ddraw);
10074 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
10075 * (color key doesn't match although the values are equal), and a false
10076 * positive when the color key is 0 and the texture contains the value 1.
10077 * I don't want to mark this broken unconditionally since this would
10078 * essentially disable the test on Windows. Also on random occasions
10079 * 254 == 255 and 255 != 255.*/
10080 is_warp = ddraw_is_warp(ddraw);
10082 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
10083 viewport = create_viewport(device, 0, 0, 640, 480);
10084 viewport_set_background(device, viewport, green);
10085 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
10086 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
10088 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10089 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
10090 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
10091 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
10092 /* There's no way to ignore the texture color in d3d2, so multiply the texture color
10093 * with a black vertex color. */
10094 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATEALPHA);
10095 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10097 memset(&fx, 0, sizeof(fx));
10098 fx.dwSize = sizeof(fx);
10099 memset(&lock_desc, 0, sizeof(lock_desc));
10100 lock_desc.dwSize = sizeof(lock_desc);
10102 for (t = 0; t < ARRAY_SIZE(tests); ++t)
10104 if (is_nvidia && tests[t].skip_nv)
10106 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
10107 continue;
10110 memset(&surface_desc, 0, sizeof(surface_desc));
10111 surface_desc.dwSize = sizeof(surface_desc);
10112 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10113 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10114 surface_desc.dwWidth = 4;
10115 surface_desc.dwHeight = 1;
10116 surface_desc.ddpfPixelFormat = tests[t].fmt;
10117 /* Windows XP (at least with the r200 driver, other drivers untested) produces
10118 * garbage when doing color keyed texture->texture blits. */
10119 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src, NULL);
10120 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10121 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst, NULL);
10122 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10124 U5(fx).dwFillColor = tests[t].clear;
10125 /* On the w8 testbot (WARP driver) the blit result has different values in the
10126 * X channel. */
10127 color_mask = U2(tests[t].fmt).dwRBitMask
10128 | U3(tests[t].fmt).dwGBitMask
10129 | U4(tests[t].fmt).dwBBitMask;
10131 for (c = 0; c <= tests[t].max; ++c)
10133 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
10134 * texture after it has been set once... */
10135 surface_desc.dwFlags |= DDSD_CKSRCBLT;
10136 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10137 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
10138 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
10139 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &texture, NULL);
10140 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10142 hr = IDirectDrawSurface4_QueryInterface(texture, &IID_IDirect3DTexture2, (void **)&d3d_texture);
10143 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
10144 hr = IDirect3DTexture2_GetHandle(d3d_texture, device, &handle);
10145 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
10146 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, handle);
10147 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
10148 IDirect3DTexture2_Release(d3d_texture);
10150 hr = IDirectDrawSurface_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10151 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
10153 hr = IDirectDrawSurface_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10154 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10155 switch (tests[t].bpp)
10157 case 4:
10158 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10159 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10160 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10161 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
10162 break;
10164 case 2:
10165 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10166 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10167 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10168 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
10169 break;
10171 hr = IDirectDrawSurface_Unlock(src, 0);
10172 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10173 hr = IDirectDrawSurface_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
10174 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10176 ckey.dwColorSpaceLowValue = c << tests[t].shift;
10177 ckey.dwColorSpaceHighValue = c << tests[t].shift;
10178 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
10179 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10181 hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
10182 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10184 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
10185 hr = IDirectDrawSurface_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10186 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10187 switch (tests[t].bpp)
10189 case 4:
10190 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
10191 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
10192 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
10193 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
10194 break;
10196 case 2:
10197 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
10198 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
10199 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
10200 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
10201 break;
10203 hr = IDirectDrawSurface_Unlock(dst, 0);
10204 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10206 if (!c)
10208 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10209 tests[t].clear, data[0], tests[t].name, c);
10211 if (data[3] == tests[t].clear)
10213 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
10214 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
10215 * even when a different surface is used. The blit itself doesn't draw anything,
10216 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
10217 * never be masked out by the key.
10219 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
10220 * test is disabled entirely.
10222 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
10223 * terrible on WARP. */
10224 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
10225 IDirectDrawSurface_Release(texture);
10226 IDirectDrawSurface_Release(src);
10227 IDirectDrawSurface_Release(dst);
10228 goto done;
10231 else
10232 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10233 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
10235 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10236 tests[t].clear, data[1], tests[t].name, c);
10238 if (c == tests[t].max)
10239 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10240 tests[t].clear, data[2], tests[t].name, c);
10241 else
10242 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10243 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
10245 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
10246 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10248 hr = IDirect3DDevice2_BeginScene(device);
10249 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10250 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
10251 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10252 hr = IDirect3DDevice2_EndScene(device);
10253 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10255 color = get_surface_color(rt, 80, 240);
10256 if (!c)
10257 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10258 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10259 color, tests[t].name, c);
10260 else
10261 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
10262 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10263 color, tests[t].name, c);
10265 color = get_surface_color(rt, 240, 240);
10266 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10267 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10268 color, tests[t].name, c);
10270 color = get_surface_color(rt, 400, 240);
10271 if (c == tests[t].max)
10272 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10273 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10274 color, tests[t].name, c);
10275 else
10276 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
10277 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10278 color, tests[t].name, c);
10280 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
10281 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
10282 IDirectDrawSurface_Release(texture);
10284 IDirectDrawSurface_Release(src);
10285 IDirectDrawSurface_Release(dst);
10287 done:
10289 destroy_viewport(device, viewport);
10290 destroy_material(green);
10291 IDirectDrawSurface_Release(rt);
10292 IDirect3DDevice2_Release(device);
10293 refcount = IDirectDraw2_Release(ddraw);
10294 ok(refcount == 0, "Ddraw object not properly released, refcount %u.\n", refcount);
10295 DestroyWindow(window);
10298 static void test_range_colorkey(void)
10300 IDirectDraw2 *ddraw;
10301 HWND window;
10302 HRESULT hr;
10303 IDirectDrawSurface *surface;
10304 DDSURFACEDESC surface_desc;
10305 ULONG refcount;
10306 DDCOLORKEY ckey;
10308 window = create_window();
10309 ddraw = create_ddraw();
10310 ok(!!ddraw, "Failed to create a ddraw object.\n");
10311 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10312 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10314 memset(&surface_desc, 0, sizeof(surface_desc));
10315 surface_desc.dwSize = sizeof(surface_desc);
10316 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
10317 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10318 surface_desc.dwWidth = 1;
10319 surface_desc.dwHeight = 1;
10320 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
10321 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
10322 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10323 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10324 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
10325 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
10327 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
10328 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10329 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10330 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10331 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10333 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10334 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10335 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10336 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10338 /* Same for DDSCAPS_OFFSCREENPLAIN. */
10339 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10340 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10341 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10342 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10343 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10345 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10346 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10347 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10348 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10350 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10351 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10352 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10353 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10355 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
10356 ckey.dwColorSpaceLowValue = 0x00000000;
10357 ckey.dwColorSpaceHighValue = 0x00000001;
10358 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10359 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10361 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10362 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10363 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10364 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10366 ckey.dwColorSpaceLowValue = 0x00000001;
10367 ckey.dwColorSpaceHighValue = 0x00000000;
10368 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10369 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10371 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10372 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10373 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10374 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10376 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
10377 ckey.dwColorSpaceLowValue = 0x00000000;
10378 ckey.dwColorSpaceHighValue = 0x00000000;
10379 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10380 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10382 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
10383 ckey.dwColorSpaceLowValue = 0x00000001;
10384 ckey.dwColorSpaceHighValue = 0x00000000;
10385 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10386 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10387 ckey.dwColorSpaceLowValue = 0x00000000;
10388 ckey.dwColorSpaceHighValue = 0x00000001;
10389 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10390 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10391 /* Range destination keys don't work either. */
10392 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
10393 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10395 /* Just to show it's not because of A, R, and G having equal values. */
10396 ckey.dwColorSpaceLowValue = 0x00000000;
10397 ckey.dwColorSpaceHighValue = 0x01010101;
10398 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10399 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10401 /* None of these operations modified the key. */
10402 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10403 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10404 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10405 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10407 IDirectDrawSurface_Release(surface);
10408 refcount = IDirectDraw2_Release(ddraw);
10409 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10410 DestroyWindow(window);
10413 static void test_shademode(void)
10415 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10416 IDirect3DMaterial2 *background;
10417 IDirect3DViewport2 *viewport;
10418 IDirect3DDevice2 *device;
10419 IDirectDrawSurface *rt;
10420 DWORD color0, color1;
10421 IDirectDraw2 *ddraw;
10422 D3DLVERTEX *quad;
10423 ULONG refcount;
10424 UINT i, count;
10425 HWND window;
10426 HRESULT hr;
10427 static D3DLVERTEX quad_strip[] =
10429 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
10430 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
10431 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
10432 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
10434 quad_list[] =
10436 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}},
10437 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
10438 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
10440 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff0000ff}},
10441 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
10442 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffffffff}},
10444 static const struct
10446 DWORD primtype;
10447 DWORD shademode;
10448 DWORD color0, color1;
10450 tests[] =
10452 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
10453 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10454 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10455 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10456 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
10457 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10460 window = create_window();
10461 ddraw = create_ddraw();
10462 ok(!!ddraw, "Failed to create a ddraw object.\n");
10463 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
10465 skip("Failed to create a 3D device, skipping test.\n");
10466 IDirectDraw2_Release(ddraw);
10467 DestroyWindow(window);
10468 return;
10471 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
10472 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10474 background = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
10475 viewport = create_viewport(device, 0, 0, 640, 480);
10476 viewport_set_background(device, viewport, background);
10477 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
10478 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
10480 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
10481 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
10483 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
10484 * the color fixups we have to do for FLAT shading will be dependent on that. */
10486 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10488 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
10489 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
10491 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
10492 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
10494 hr = IDirect3DDevice2_BeginScene(device);
10495 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10496 quad = tests[i].primtype == D3DPT_TRIANGLESTRIP ? quad_strip : quad_list;
10497 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
10498 hr = IDirect3DDevice2_DrawPrimitive(device, tests[i].primtype, D3DVT_LVERTEX, quad, count, 0);
10499 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10500 hr = IDirect3DDevice2_EndScene(device);
10501 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10503 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
10504 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
10506 /* For D3DSHADE_FLAT it should take the color of the first vertex of
10507 * each triangle. This requires EXT_provoking_vertex or similar
10508 * functionality being available. */
10509 /* PHONG should be the same as GOURAUD, since no hardware implements
10510 * this. */
10511 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
10512 i, color0, tests[i].color0);
10513 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
10514 i, color1, tests[i].color1);
10517 destroy_viewport(device, viewport);
10518 destroy_material(background);
10519 IDirectDrawSurface_Release(rt);
10520 refcount = IDirect3DDevice2_Release(device);
10521 ok(!refcount, "Device has %u references left.\n", refcount);
10522 IDirectDraw2_Release(ddraw);
10523 DestroyWindow(window);
10526 static void test_lockrect_invalid(void)
10528 unsigned int i, r;
10529 IDirectDraw2 *ddraw;
10530 IDirectDrawSurface *surface1;
10531 IDirectDrawSurface2 *surface;
10532 HWND window;
10533 HRESULT hr;
10534 DDSURFACEDESC surface_desc;
10535 DDCAPS hal_caps;
10536 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
10537 static RECT valid[] =
10539 {60, 60, 68, 68},
10540 {60, 60, 60, 68},
10541 {60, 60, 68, 60},
10542 {120, 60, 128, 68},
10543 {60, 120, 68, 128},
10545 static RECT invalid[] =
10547 {68, 60, 60, 68}, /* left > right */
10548 {60, 68, 68, 60}, /* top > bottom */
10549 {-8, 60, 0, 68}, /* left < surface */
10550 {60, -8, 68, 0}, /* top < surface */
10551 {-16, 60, -8, 68}, /* right < surface */
10552 {60, -16, 68, -8}, /* bottom < surface */
10553 {60, 60, 136, 68}, /* right > surface */
10554 {60, 60, 68, 136}, /* bottom > surface */
10555 {136, 60, 144, 68}, /* left > surface */
10556 {60, 136, 68, 144}, /* top > surface */
10558 static const struct
10560 DWORD caps;
10561 const char *name;
10562 HRESULT hr;
10564 resources[] =
10566 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, "sysmem offscreenplain", DDERR_INVALIDPARAMS},
10567 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, "vidmem offscreenplain", DDERR_INVALIDPARAMS},
10568 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "sysmem texture", DDERR_INVALIDPARAMS},
10569 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "vidmem texture", DDERR_INVALIDPARAMS},
10572 window = create_window();
10573 ddraw = create_ddraw();
10574 ok(!!ddraw, "Failed to create a ddraw object.\n");
10575 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10576 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10578 memset(&hal_caps, 0, sizeof(hal_caps));
10579 hal_caps.dwSize = sizeof(hal_caps);
10580 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
10581 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10582 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
10584 skip("Required surface types not supported, skipping test.\n");
10585 goto done;
10588 for (r = 0; r < ARRAY_SIZE(resources); ++r)
10590 memset(&surface_desc, 0, sizeof(surface_desc));
10591 surface_desc.dwSize = sizeof(surface_desc);
10592 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10593 surface_desc.ddsCaps.dwCaps = resources[r].caps;
10594 surface_desc.dwWidth = 128;
10595 surface_desc.dwHeight = 128;
10596 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
10597 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
10598 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
10599 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xff0000;
10600 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x00ff00;
10601 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x0000ff;
10603 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
10604 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
10605 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
10606 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface2 interface, hr %#x.\n", hr);
10607 IDirectDrawSurface_Release(surface1);
10609 hr = IDirectDrawSurface2_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
10610 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
10612 for (i = 0; i < ARRAY_SIZE(valid); ++i)
10614 RECT *rect = &valid[i];
10616 memset(&surface_desc, 0, sizeof(surface_desc));
10617 surface_desc.dwSize = sizeof(surface_desc);
10619 hr = IDirectDrawSurface2_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
10620 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect %s, type %s.\n",
10621 hr, wine_dbgstr_rect(rect), resources[r].name);
10623 hr = IDirectDrawSurface2_Unlock(surface, NULL);
10624 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
10627 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
10629 RECT *rect = &invalid[i];
10631 memset(&surface_desc, 1, sizeof(surface_desc));
10632 surface_desc.dwSize = sizeof(surface_desc);
10634 hr = IDirectDrawSurface2_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
10635 ok(hr == resources[r].hr, "Lock returned %#x for rect %s, type %s.\n",
10636 hr, wine_dbgstr_rect(rect), resources[r].name);
10637 if (SUCCEEDED(hr))
10639 hr = IDirectDrawSurface2_Unlock(surface, NULL);
10640 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
10642 else
10643 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
10646 hr = IDirectDrawSurface2_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
10647 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
10648 hr, resources[r].name);
10649 hr = IDirectDrawSurface2_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
10650 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
10651 hr, resources[r].name);
10652 hr = IDirectDrawSurface2_Unlock(surface, NULL);
10653 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
10655 hr = IDirectDrawSurface2_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
10656 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#x).\n", wine_dbgstr_rect(&valid[0]), hr);
10657 hr = IDirectDrawSurface2_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
10658 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#x).\n",
10659 wine_dbgstr_rect(&valid[0]), hr);
10661 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
10662 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
10664 hr = IDirectDrawSurface2_Unlock(surface, NULL);
10665 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
10667 IDirectDrawSurface2_Release(surface);
10670 done:
10671 IDirectDraw2_Release(ddraw);
10672 DestroyWindow(window);
10675 static void test_yv12_overlay(void)
10677 IDirectDrawSurface *src_surface, *dst_surface;
10678 RECT rect = {13, 17, 14, 18};
10679 unsigned int offset, y;
10680 unsigned char *base;
10681 IDirectDraw2 *ddraw;
10682 DDSURFACEDESC desc;
10683 HWND window;
10684 HRESULT hr;
10686 window = create_window();
10687 ddraw = create_ddraw();
10688 ok(!!ddraw, "Failed to create a ddraw object.\n");
10689 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10690 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10692 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
10694 skip("Failed to create a YV12 overlay, skipping test.\n");
10695 goto done;
10698 memset(&desc, 0, sizeof(desc));
10699 desc.dwSize = sizeof(desc);
10700 hr = IDirectDrawSurface_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
10701 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10703 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
10704 "Got unexpected flags %#x.\n", desc.dwFlags);
10705 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
10706 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
10707 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
10708 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
10709 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
10710 /* The overlay pitch seems to have 256 byte alignment. */
10711 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
10713 /* Fill the surface with some data for the blit test. */
10714 base = desc.lpSurface;
10715 /* Luminance */
10716 for (y = 0; y < desc.dwHeight; ++y)
10718 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
10720 /* V */
10721 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
10723 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
10725 /* U */
10726 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
10728 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
10731 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
10732 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10734 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
10735 * other block-based formats like DXT the entire Y channel is stored in
10736 * one big chunk of memory, followed by the chroma channels. So partial
10737 * locks do not really make sense. Show that they are allowed nevertheless
10738 * and the offset points into the luminance data. */
10739 hr = IDirectDrawSurface_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
10740 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10741 offset = ((const unsigned char *)desc.lpSurface - base);
10742 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
10743 offset, rect.top * U1(desc).lPitch + rect.left);
10744 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
10745 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10747 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
10749 /* Windows XP with a Radeon X1600 GPU refuses to create a second
10750 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
10751 skip("Failed to create a second YV12 surface, skipping blit test.\n");
10752 IDirectDrawSurface_Release(src_surface);
10753 goto done;
10756 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
10757 /* VMware rejects YV12 blits. This behavior has not been seen on real
10758 * hardware yet, so mark it broken. */
10759 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
10761 if (SUCCEEDED(hr))
10763 memset(&desc, 0, sizeof(desc));
10764 desc.dwSize = sizeof(desc);
10765 hr = IDirectDrawSurface_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
10766 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10768 base = desc.lpSurface;
10769 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
10770 base += desc.dwHeight * U1(desc).lPitch;
10771 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
10772 base += desc.dwHeight / 4 * U1(desc).lPitch;
10773 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
10775 hr = IDirectDrawSurface_Unlock(dst_surface, NULL);
10776 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10779 IDirectDrawSurface_Release(dst_surface);
10780 IDirectDrawSurface_Release(src_surface);
10781 done:
10782 IDirectDraw2_Release(ddraw);
10783 DestroyWindow(window);
10786 static BOOL dwm_enabled(void)
10788 BOOL ret = FALSE;
10790 if (!strcmp(winetest_platform, "wine"))
10791 return FALSE;
10792 if (!pDwmIsCompositionEnabled)
10793 return FALSE;
10794 if (FAILED(pDwmIsCompositionEnabled(&ret)))
10795 return FALSE;
10796 return ret;
10799 static void test_offscreen_overlay(void)
10801 IDirectDrawSurface *overlay, *offscreen, *primary;
10802 DDSURFACEDESC surface_desc;
10803 IDirectDraw2 *ddraw;
10804 HWND window;
10805 HRESULT hr;
10806 HDC dc;
10808 window = create_window();
10809 ddraw = create_ddraw();
10810 ok(!!ddraw, "Failed to create a ddraw object.\n");
10811 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10812 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10814 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
10816 skip("Failed to create a UYVY overlay, skipping test.\n");
10817 goto done;
10820 memset(&surface_desc, 0, sizeof(surface_desc));
10821 surface_desc.dwSize = sizeof(surface_desc);
10822 surface_desc.dwFlags = DDSD_CAPS;
10823 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
10824 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
10825 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
10827 /* On Windows 7, and probably Vista, UpdateOverlay() will return
10828 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
10829 * surface prevents this by disabling the dwm. */
10830 hr = IDirectDrawSurface_GetDC(primary, &dc);
10831 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
10832 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
10833 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
10835 /* Try to overlay a NULL surface. */
10836 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
10837 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10838 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
10839 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10841 /* Try to overlay an offscreen surface. */
10842 memset(&surface_desc, 0, sizeof(surface_desc));
10843 surface_desc.dwSize = sizeof(surface_desc);
10844 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
10845 surface_desc.dwWidth = 64;
10846 surface_desc.dwHeight = 64;
10847 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10848 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
10849 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
10850 surface_desc.ddpfPixelFormat.dwFourCC = 0;
10851 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
10852 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
10853 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
10854 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
10855 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
10856 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
10858 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
10859 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled())
10860 || broken(hr == E_NOTIMPL && ddraw_is_vmware(ddraw)),
10861 "Failed to update overlay, hr %#x.\n", hr);
10863 /* Try to overlay the primary with a non-overlay surface. */
10864 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
10865 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
10866 hr = IDirectDrawSurface_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
10867 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
10869 IDirectDrawSurface_Release(offscreen);
10870 IDirectDrawSurface_Release(primary);
10871 IDirectDrawSurface_Release(overlay);
10872 done:
10873 IDirectDraw2_Release(ddraw);
10874 DestroyWindow(window);
10877 static void test_overlay_rect(void)
10879 IDirectDrawSurface *overlay, *primary = NULL;
10880 DDSURFACEDESC surface_desc;
10881 RECT rect = {0, 0, 64, 64};
10882 IDirectDraw2 *ddraw;
10883 LONG pos_x, pos_y;
10884 HRESULT hr, hr2;
10885 HWND window;
10886 HDC dc;
10888 window = create_window();
10889 ddraw = create_ddraw();
10890 ok(!!ddraw, "Failed to create a ddraw object.\n");
10891 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10892 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10894 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
10896 skip("Failed to create a UYVY overlay, skipping test.\n");
10897 goto done;
10900 memset(&surface_desc, 0, sizeof(surface_desc));
10901 surface_desc.dwSize = sizeof(surface_desc);
10902 surface_desc.dwFlags = DDSD_CAPS;
10903 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
10904 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
10905 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
10907 /* On Windows 7, and probably Vista, UpdateOverlay() will return
10908 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
10909 * surface prevents this by disabling the dwm. */
10910 hr = IDirectDrawSurface_GetDC(primary, &dc);
10911 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
10912 hr = IDirectDrawSurface_ReleaseDC(primary, dc);
10913 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
10915 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
10916 if (dwm_enabled())
10918 win_skip("Cannot disable DWM, skipping overlay test.\n");
10919 goto done;
10922 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
10923 * used. This is not true in Windows Vista and earlier, but changed in
10924 * Windows 7. */
10925 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
10926 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
10927 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
10928 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
10929 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
10930 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10932 /* Show that the overlay position is the (top, left) coordinate of the
10933 * destination rectangle. */
10934 OffsetRect(&rect, 32, 16);
10935 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
10936 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
10937 pos_x = -1; pos_y = -1;
10938 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
10939 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
10940 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
10941 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
10943 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
10944 * seen that the overlay overlays the whole primary(==screen). */
10945 hr2 = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
10946 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
10947 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
10948 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
10949 if (SUCCEEDED(hr2))
10951 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
10952 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
10954 else
10956 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
10957 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
10960 /* The position cannot be retrieved when the overlay is not shown. */
10961 hr = IDirectDrawSurface_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
10962 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
10963 pos_x = -1; pos_y = -1;
10964 hr = IDirectDrawSurface_GetOverlayPosition(overlay, &pos_x, &pos_y);
10965 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
10966 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
10967 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
10969 done:
10970 if (primary)
10971 IDirectDrawSurface_Release(primary);
10972 if (overlay)
10973 IDirectDrawSurface_Release(overlay);
10974 IDirectDraw2_Release(ddraw);
10975 DestroyWindow(window);
10978 static void test_blt(void)
10980 IDirectDrawSurface *surface, *rt;
10981 DDSURFACEDESC surface_desc;
10982 IDirect3DDevice2 *device;
10983 IDirectDraw2 *ddraw;
10984 unsigned int i;
10985 ULONG refcount;
10986 HWND window;
10987 HRESULT hr;
10989 static struct
10991 RECT src_rect;
10992 RECT dst_rect;
10993 HRESULT hr;
10995 test_data[] =
10997 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
10998 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
10999 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
11000 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
11001 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
11002 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
11003 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
11004 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
11005 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
11006 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
11009 window = create_window();
11010 ddraw = create_ddraw();
11011 ok(!!ddraw, "Failed to create a ddraw object.\n");
11012 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
11014 skip("Failed to create a 3D device, skipping test.\n");
11015 IDirectDraw2_Release(ddraw);
11016 DestroyWindow(window);
11017 return;
11020 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
11021 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11023 memset(&surface_desc, 0, sizeof(surface_desc));
11024 surface_desc.dwSize = sizeof(surface_desc);
11025 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
11026 surface_desc.dwWidth = 640;
11027 surface_desc.dwHeight = 480;
11028 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11029 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11030 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11032 hr = IDirectDrawSurface_Blt(surface, NULL, surface, NULL, 0, NULL);
11033 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11035 hr = IDirectDrawSurface_Blt(surface, NULL, rt, NULL, 0, NULL);
11036 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11038 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
11040 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
11041 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11042 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
11044 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
11045 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11046 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
11048 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
11049 NULL, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11050 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
11052 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect, NULL, NULL, DDBLT_WAIT, NULL);
11053 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
11056 IDirectDrawSurface_Release(surface);
11057 IDirectDrawSurface_Release(rt);
11058 refcount = IDirect3DDevice2_Release(device);
11059 ok(!refcount, "Device has %u references left.\n", refcount);
11060 IDirectDraw2_Release(ddraw);
11061 DestroyWindow(window);
11064 static void test_blt_z_alpha(void)
11066 DWORD blt_flags[] =
11068 /* 0 */
11069 DDBLT_ALPHADEST,
11070 DDBLT_ALPHADESTCONSTOVERRIDE,
11071 DDBLT_ALPHADESTNEG,
11072 DDBLT_ALPHADESTSURFACEOVERRIDE,
11073 DDBLT_ALPHAEDGEBLEND,
11074 /* 5 */
11075 DDBLT_ALPHASRC,
11076 DDBLT_ALPHASRCCONSTOVERRIDE,
11077 DDBLT_ALPHASRCNEG,
11078 DDBLT_ALPHASRCSURFACEOVERRIDE,
11079 DDBLT_ZBUFFER,
11080 /* 10 */
11081 DDBLT_ZBUFFERDESTCONSTOVERRIDE,
11082 DDBLT_ZBUFFERDESTOVERRIDE,
11083 DDBLT_ZBUFFERSRCCONSTOVERRIDE,
11084 DDBLT_ZBUFFERSRCOVERRIDE,
11086 IDirectDrawSurface *src_surface, *dst_surface;
11087 DDSURFACEDESC surface_desc;
11088 IDirectDraw2 *ddraw;
11089 DDPIXELFORMAT pf;
11090 ULONG refcount;
11091 unsigned int i;
11092 D3DCOLOR color;
11093 HWND window;
11094 HRESULT hr;
11095 DDBLTFX fx;
11097 window = create_window();
11098 ddraw = create_ddraw();
11099 ok(!!ddraw, "Failed to create a ddraw object.\n");
11100 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11101 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11103 memset(&pf, 0, sizeof(pf));
11104 pf.dwSize = sizeof(pf);
11105 pf.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
11106 U1(pf).dwRGBBitCount = 32;
11107 U2(pf).dwRBitMask = 0x00ff0000;
11108 U3(pf).dwGBitMask = 0x0000ff00;
11109 U4(pf).dwBBitMask = 0x000000ff;
11110 U5(pf).dwRGBAlphaBitMask = 0xff000000;
11112 memset(&surface_desc, 0, sizeof(surface_desc));
11113 surface_desc.dwSize = sizeof(surface_desc);
11114 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
11115 surface_desc.dwWidth = 64;
11116 surface_desc.dwHeight = 64;
11117 surface_desc.ddpfPixelFormat = pf;
11118 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11120 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
11121 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
11122 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
11123 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
11125 memset(&fx, 0, sizeof(fx));
11126 fx.dwSize = sizeof(fx);
11127 fx.dwZBufferOpCode = D3DCMP_NEVER;
11128 fx.dwZDestConstBitDepth = 32;
11129 U1(fx).dwZDestConst = 0x11111111;
11130 fx.dwZSrcConstBitDepth = 32;
11131 U2(fx).dwZSrcConst = 0xeeeeeeee;
11132 fx.dwAlphaEdgeBlendBitDepth = 8;
11133 fx.dwAlphaEdgeBlend = 0x7f;
11134 fx.dwAlphaDestConstBitDepth = 8;
11135 U3(fx).dwAlphaDestConst = 0xdd;
11136 fx.dwAlphaSrcConstBitDepth = 8;
11137 U4(fx).dwAlphaSrcConst = 0x22;
11139 for (i = 0; i < ARRAY_SIZE(blt_flags); ++i)
11141 U5(fx).dwFillColor = 0x3300ff00;
11142 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11143 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
11145 U5(fx).dwFillColor = 0xccff0000;
11146 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11147 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
11149 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, NULL, blt_flags[i] | DDBLT_WAIT, &fx);
11150 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
11152 color = get_surface_color(dst_surface, 32, 32);
11153 ok(compare_color(color, 0x0000ff00, 0), "Test %u: Got unexpected color 0x%08x.\n", i, color);
11156 IDirectDrawSurface_Release(dst_surface);
11157 IDirectDrawSurface_Release(src_surface);
11158 refcount = IDirectDraw2_Release(ddraw);
11159 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
11160 DestroyWindow(window);
11163 static void test_cross_device_blt(void)
11165 IDirectDrawSurface *surface, *surface2, *sysmem_surface;
11166 IDirect3DDevice2 *device, *device2;
11167 IDirectDraw2 *ddraw, *ddraw2;
11168 DDSURFACEDESC surface_desc;
11169 HWND window, window2;
11170 ULONG refcount;
11171 D3DCOLOR color;
11172 DDBLTFX fx;
11173 HRESULT hr;
11175 window = create_window();
11176 ddraw = create_ddraw();
11177 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
11179 skip("Failed to create a 3D device.\n");
11180 IDirectDraw2_Release(ddraw);
11181 DestroyWindow(window);
11182 return;
11185 window2 = create_window();
11186 ddraw2 = create_ddraw();
11187 if (!(device2 = create_device(ddraw2, window2, DDSCL_NORMAL)))
11189 skip("Failed to create a 3D device.\n");
11190 IDirectDraw2_Release(ddraw2);
11191 IDirect3DDevice2_Release(device);
11192 IDirectDraw2_Release(ddraw);
11193 DestroyWindow(window);
11194 DestroyWindow(window2);
11195 return;
11198 memset(&surface_desc, 0, sizeof(surface_desc));
11199 surface_desc.dwSize = sizeof(surface_desc);
11200 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
11201 surface_desc.dwWidth = 640;
11202 surface_desc.dwHeight = 480;
11203 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
11204 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
11205 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11207 memset(&surface_desc, 0, sizeof(surface_desc));
11208 surface_desc.dwSize = sizeof(surface_desc);
11209 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
11210 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
11211 surface_desc.dwBackBufferCount = 2;
11212 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11213 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11215 memset(&surface_desc, 0, sizeof(surface_desc));
11216 surface_desc.dwSize = sizeof(surface_desc);
11217 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
11218 surface_desc.dwWidth = 640;
11219 surface_desc.dwHeight = 480;
11220 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
11221 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
11222 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
11223 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
11224 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00007c00;
11225 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x000003e0;
11226 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x0000001f;
11227 hr = IDirectDraw2_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
11228 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11230 memset(&fx, 0, sizeof(fx));
11231 fx.dwSize = sizeof(fx);
11232 U5(fx).dwFillColor = 0xff0000ff;
11233 hr = IDirectDrawSurface_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11234 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
11236 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
11237 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
11238 hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
11239 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11240 hr = IDirectDrawSurface_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
11241 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
11242 color = get_surface_color(surface, 320, 240);
11243 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
11245 hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
11246 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
11247 color = get_surface_color(sysmem_surface, 320, 240);
11248 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
11250 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11251 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11252 hr = IDirectDrawSurface_IsLost(sysmem_surface);
11253 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11255 hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
11256 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
11257 color = get_surface_color(sysmem_surface, 320, 240);
11258 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
11260 IDirectDrawSurface_Release(surface2);
11261 memset(&surface_desc, 0, sizeof(surface_desc));
11262 surface_desc.dwSize = sizeof(surface_desc);
11263 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
11264 surface_desc.dwWidth = 640;
11265 surface_desc.dwHeight = 480;
11266 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
11267 hr = IDirectDraw2_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
11268 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11269 hr = IDirectDrawSurface_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11270 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
11272 hr = IDirectDrawSurface_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
11273 todo_wine ok(hr == D3D_OK, "Failed to blit, hr %#x.\n", hr);
11274 color = get_surface_color(sysmem_surface, 320, 240);
11275 todo_wine ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
11277 IDirectDrawSurface_Release(surface);
11278 IDirectDrawSurface_Release(surface2);
11279 IDirectDrawSurface_Release(sysmem_surface);
11280 refcount = IDirect3DDevice2_Release(device);
11281 ok(!refcount, "Device has %u references left.\n", refcount);
11282 refcount = IDirect3DDevice2_Release(device2);
11283 ok(!refcount, "Device has %u references left.\n", refcount);
11284 IDirectDraw2_Release(ddraw);
11285 IDirectDraw2_Release(ddraw2);
11286 DestroyWindow(window);
11287 DestroyWindow(window2);
11290 static void test_getdc(void)
11292 IDirectDrawSurface *surface, *surface2, *tmp;
11293 DDSURFACEDESC surface_desc, map_desc;
11294 DDSCAPS caps = {DDSCAPS_COMPLEX};
11295 IDirectDraw2 *ddraw;
11296 unsigned int i, screen_bpp;
11297 HWND window;
11298 HDC dc, dc2;
11299 HRESULT hr;
11301 static const struct
11303 const char *name;
11304 DDPIXELFORMAT format;
11305 BOOL getdc_supported;
11306 HRESULT alt_result;
11308 test_data[] =
11310 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11311 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
11312 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
11313 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
11314 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11315 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
11316 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11317 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
11318 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
11319 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
11320 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
11321 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11322 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11323 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11324 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11325 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
11326 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11327 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11328 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
11329 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11330 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
11331 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
11332 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
11333 * This is not implemented in wine yet, so disable the test for now.
11334 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
11335 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
11336 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11338 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
11339 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11340 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
11341 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
11342 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
11343 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11344 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
11345 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11346 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
11347 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11348 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
11349 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11350 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
11351 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11354 window = create_window();
11355 ddraw = create_ddraw();
11356 ok(!!ddraw, "Failed to create a ddraw object.\n");
11357 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11358 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11360 surface_desc.dwSize = sizeof(surface_desc);
11361 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
11362 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
11363 screen_bpp = U1(surface_desc.ddpfPixelFormat).dwRGBBitCount;
11365 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
11367 memset(&surface_desc, 0, sizeof(surface_desc));
11368 surface_desc.dwSize = sizeof(surface_desc);
11369 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11370 surface_desc.dwWidth = 64;
11371 surface_desc.dwHeight = 64;
11372 surface_desc.ddpfPixelFormat = test_data[i].format;
11373 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11375 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11377 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11378 if (FAILED(hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11380 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
11381 continue;
11385 dc = (void *)0x1234;
11386 hr = IDirectDrawSurface_GetDC(surface, &dc);
11387 if (test_data[i].getdc_supported)
11388 ok(SUCCEEDED(hr) || broken(hr == test_data[i].alt_result || ddraw_is_vmware(ddraw)),
11389 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11390 else
11391 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11393 if (SUCCEEDED(hr))
11395 unsigned int width_bytes;
11396 DIBSECTION dib;
11397 HBITMAP bitmap;
11398 DWORD type;
11399 int size;
11401 type = GetObjectType(dc);
11402 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
11403 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
11404 type = GetObjectType(bitmap);
11405 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
11407 size = GetObjectA(bitmap, sizeof(dib), &dib);
11408 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
11409 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
11410 dib.dsBm.bmType, test_data[i].name);
11411 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
11412 dib.dsBm.bmWidth, test_data[i].name);
11413 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
11414 dib.dsBm.bmHeight, test_data[i].name);
11415 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
11416 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
11417 dib.dsBm.bmWidthBytes, test_data[i].name);
11418 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
11419 dib.dsBm.bmPlanes, test_data[i].name);
11420 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
11421 "Got unexpected bit count %d for format %s.\n",
11422 dib.dsBm.bmBitsPixel, test_data[i].name);
11423 /* Windows XP sets bmBits == NULL for formats that match the screen at least on my r200 GPU. I
11424 * suspect this applies to all HW accelerated pre-WDDM drivers because they can handle gdi access
11425 * to ddraw surfaces themselves instead of going through a sysmem DIB section. */
11426 ok(!!dib.dsBm.bmBits || broken(!pDwmIsCompositionEnabled && dib.dsBm.bmBitsPixel == screen_bpp),
11427 "Got unexpected bits %p for format %s.\n", dib.dsBm.bmBits, test_data[i].name);
11429 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
11430 dib.dsBmih.biSize, test_data[i].name);
11431 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
11432 dib.dsBmih.biHeight, test_data[i].name);
11433 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
11434 dib.dsBmih.biHeight, test_data[i].name);
11435 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
11436 dib.dsBmih.biPlanes, test_data[i].name);
11437 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
11438 "Got unexpected bit count %u for format %s.\n",
11439 dib.dsBmih.biBitCount, test_data[i].name);
11440 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
11441 || broken(U1(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
11442 "Got unexpected compression %#x for format %s.\n",
11443 dib.dsBmih.biCompression, test_data[i].name);
11444 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
11445 dib.dsBmih.biSizeImage, test_data[i].name);
11446 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
11447 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
11448 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
11449 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
11450 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
11451 dib.dsBmih.biClrUsed, test_data[i].name);
11452 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
11453 dib.dsBmih.biClrImportant, test_data[i].name);
11455 if (dib.dsBmih.biCompression == BI_BITFIELDS)
11457 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
11458 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
11459 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
11460 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
11461 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
11462 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11464 else
11466 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
11467 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
11468 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11470 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
11471 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
11473 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11474 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11476 else
11478 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
11481 IDirectDrawSurface_Release(surface);
11483 if (FAILED(hr))
11484 continue;
11486 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
11487 if (FAILED(hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11489 skip("Failed to create mip-mapped texture for format %s (hr %#x), skipping tests.\n",
11490 test_data[i].name, hr);
11491 continue;
11494 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
11495 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
11496 hr = IDirectDrawSurface_GetAttachedSurface(tmp, &caps, &surface2);
11497 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
11498 IDirectDrawSurface_Release(tmp);
11500 hr = IDirectDrawSurface_GetDC(surface, &dc);
11501 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11502 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11503 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11504 hr = IDirectDrawSurface_GetDC(surface2, &dc);
11505 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11506 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
11507 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11509 hr = IDirectDrawSurface_GetDC(surface, &dc);
11510 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11511 dc2 = (void *)0x1234;
11512 hr = IDirectDrawSurface_GetDC(surface, &dc2);
11513 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11514 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
11515 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11516 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11517 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11518 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11520 map_desc.dwSize = sizeof(map_desc);
11521 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11522 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11523 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11524 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11525 hr = IDirectDrawSurface_Unlock(surface, NULL);
11526 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11527 hr = IDirectDrawSurface_Unlock(surface, NULL);
11528 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11530 hr = IDirectDrawSurface_GetDC(surface, &dc);
11531 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11532 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11533 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11534 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11535 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11537 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11538 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11539 hr = IDirectDrawSurface_GetDC(surface, &dc);
11540 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11541 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11542 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11543 /* Geforce 9600, Windows 7 returns E_FAIL. The unlock still seems to work as intended, after-
11544 * wards the surface can be locked again. ReleaseDC() does not unlock the surface, trying to
11545 * Lock it after ReleaseDC returns DDERR_SURFACEBUSY. ddraw4 and 7 are unaffected. */
11546 hr = IDirectDrawSurface_Unlock(surface, NULL);
11547 ok(SUCCEEDED(hr) || broken(ddraw_is_nvidia(ddraw) && hr == E_FAIL),
11548 "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11550 hr = IDirectDrawSurface_GetDC(surface, &dc);
11551 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11552 hr = IDirectDrawSurface_GetDC(surface2, &dc2);
11553 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11554 hr = IDirectDrawSurface_ReleaseDC(surface2, dc2);
11555 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11556 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11557 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11559 hr = IDirectDrawSurface_GetDC(surface2, &dc);
11560 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11561 hr = IDirectDrawSurface_GetDC(surface, &dc2);
11562 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11563 hr = IDirectDrawSurface_ReleaseDC(surface, dc2);
11564 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11565 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
11566 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11568 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11569 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11570 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11571 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11572 hr = IDirectDrawSurface_Unlock(surface2, NULL);
11573 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11574 hr = IDirectDrawSurface_Unlock(surface, NULL);
11575 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11577 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11578 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11579 hr = IDirectDrawSurface_GetDC(surface, &dc);
11580 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11581 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11582 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11583 hr = IDirectDrawSurface_Unlock(surface, NULL);
11584 ok(SUCCEEDED(hr) || broken(ddraw_is_nvidia(ddraw) && hr == E_FAIL),
11585 "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11587 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11588 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11589 hr = IDirectDrawSurface_GetDC(surface, &dc);
11590 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11591 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11592 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11593 hr = IDirectDrawSurface_Unlock(surface2, NULL);
11594 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11596 hr = IDirectDrawSurface_GetDC(surface, &dc);
11597 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11598 hr = IDirectDrawSurface_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11599 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11600 hr = IDirectDrawSurface_Unlock(surface2, NULL);
11601 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11602 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11603 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11605 hr = IDirectDrawSurface_GetDC(surface2, &dc);
11606 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11607 hr = IDirectDrawSurface_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11608 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11609 hr = IDirectDrawSurface_Unlock(surface, NULL);
11610 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11611 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
11612 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11614 hr = IDirectDrawSurface_Unlock(surface, NULL);
11615 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11616 hr = IDirectDrawSurface_GetDC(surface2, &dc);
11617 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11618 hr = IDirectDrawSurface_Unlock(surface, NULL);
11619 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11620 hr = IDirectDrawSurface_ReleaseDC(surface2, dc);
11621 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11622 hr = IDirectDrawSurface_Unlock(surface, NULL);
11623 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11625 hr = IDirectDrawSurface_Unlock(surface2, NULL);
11626 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11627 hr = IDirectDrawSurface_GetDC(surface, &dc);
11628 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11629 hr = IDirectDrawSurface_Unlock(surface2, NULL);
11630 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11631 hr = IDirectDrawSurface_ReleaseDC(surface, dc);
11632 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11633 hr = IDirectDrawSurface_Unlock(surface2, NULL);
11634 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11636 IDirectDrawSurface_Release(surface2);
11637 IDirectDrawSurface_Release(surface);
11640 IDirectDraw2_Release(ddraw);
11641 DestroyWindow(window);
11644 static void test_draw_primitive(void)
11646 static WORD indices[] = {0, 1, 2, 3};
11647 static D3DVERTEX quad[] =
11649 {{-1.0f}, {-1.0f}, {0.0f}},
11650 {{-1.0f}, { 1.0f}, {0.0f}},
11651 {{ 1.0f}, {-1.0f}, {0.0f}},
11652 {{ 1.0f}, { 1.0f}, {0.0f}},
11654 IDirect3DViewport2 *viewport;
11655 IDirect3DDevice2 *device;
11656 IDirectDraw2 *ddraw;
11657 IDirect3D2 *d3d;
11658 ULONG refcount;
11659 HWND window;
11660 HRESULT hr;
11662 window = create_window();
11663 ddraw = create_ddraw();
11664 ok(!!ddraw, "Failed to create a ddraw object.\n");
11665 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
11667 skip("Failed to create a 3D device, skipping test.\n");
11668 IDirectDraw2_Release(ddraw);
11669 DestroyWindow(window);
11670 return;
11673 viewport = create_viewport(device, 0, 0, 640, 480);
11674 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
11675 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
11677 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
11678 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
11680 IDirect3D2_Release(d3d);
11682 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
11683 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11684 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
11685 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11687 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
11688 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11690 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
11691 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11692 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
11693 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11694 hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
11695 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11697 destroy_viewport(device, viewport);
11698 refcount = IDirect3DDevice2_Release(device);
11699 ok(!refcount, "Device has %u references left.\n", refcount);
11700 IDirectDraw2_Release(ddraw);
11701 DestroyWindow(window);
11704 static void test_edge_antialiasing_blending(void)
11706 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
11707 IDirect3DMaterial2 *green_background;
11708 IDirect3DMaterial2 *red_background;
11709 IDirectDrawSurface *offscreen, *ds;
11710 D3DDEVICEDESC hal_desc, hel_desc;
11711 IDirect3DViewport2 *viewport;
11712 DDSURFACEDESC surface_desc;
11713 IDirect3DDevice2 *device;
11714 IDirectDraw2 *ddraw;
11715 ULONG refcount;
11716 D3DCOLOR color;
11717 HWND window;
11718 HRESULT hr;
11720 static D3DMATRIX mat =
11722 1.0f, 0.0f, 0.0f, 0.0f,
11723 0.0f, 1.0f, 0.0f, 0.0f,
11724 0.0f, 0.0f, 1.0f, 0.0f,
11725 0.0f, 0.0f, 0.0f, 1.0f,
11727 static D3DLVERTEX green_quad[] =
11729 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0x7f00ff00}},
11730 {{-1.0f}, { 1.0f}, {0.1f}, 0, {0x7f00ff00}},
11731 {{ 1.0f}, {-1.0f}, {0.1f}, 0, {0x7f00ff00}},
11732 {{ 1.0f}, { 1.0f}, {0.1f}, 0, {0x7f00ff00}},
11734 static D3DLVERTEX red_quad[] =
11736 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0xccff0000}},
11737 {{-1.0f}, { 1.0f}, {0.1f}, 0, {0xccff0000}},
11738 {{ 1.0f}, {-1.0f}, {0.1f}, 0, {0xccff0000}},
11739 {{ 1.0f}, { 1.0f}, {0.1f}, 0, {0xccff0000}},
11742 window = create_window();
11743 ddraw = create_ddraw();
11744 ok(!!ddraw, "Failed to create a ddraw object.\n");
11745 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
11747 skip("Failed to create a 3D device.\n");
11748 DestroyWindow(window);
11749 return;
11752 memset(&hal_desc, 0, sizeof(hal_desc));
11753 hal_desc.dwSize = sizeof(hal_desc);
11754 memset(&hel_desc, 0, sizeof(hel_desc));
11755 hel_desc.dwSize = sizeof(hel_desc);
11756 hr = IDirect3DDevice2_GetCaps(device, &hal_desc, &hel_desc);
11757 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
11758 trace("HAL line edge antialiasing support: %#x.\n",
11759 hal_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
11760 trace("HAL triangle edge antialiasing support: %#x.\n",
11761 hal_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
11762 trace("HEL line edge antialiasing support: %#x.\n",
11763 hel_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
11764 trace("HEL triangle edge antialiasing support: %#x.\n",
11765 hel_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
11767 memset(&surface_desc, 0, sizeof(surface_desc));
11768 surface_desc.dwSize = sizeof(surface_desc);
11769 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
11770 surface_desc.dwWidth = 640;
11771 surface_desc.dwHeight = 480;
11772 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
11773 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
11774 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
11775 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
11776 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
11777 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
11778 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
11779 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
11780 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
11781 ok(hr == D3D_OK, "Creating the offscreen render target failed, hr %#x.\n", hr);
11783 ds = get_depth_stencil(device);
11784 hr = IDirectDrawSurface_AddAttachedSurface(offscreen, ds);
11785 todo_wine ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
11786 IDirectDrawSurface_Release(ds);
11788 hr = IDirect3DDevice2_SetRenderTarget(device, offscreen, 0);
11789 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
11791 red_background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 0.8f);
11792 green_background = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.5f);
11794 viewport = create_viewport(device, 0, 0, 640, 480);
11795 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
11796 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
11798 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
11799 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
11800 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
11801 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
11802 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
11803 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
11804 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
11805 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
11806 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
11807 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
11808 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
11809 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
11811 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
11812 ok(SUCCEEDED(hr), "Failed to enable blending, hr %#x.\n", hr);
11813 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
11814 ok(SUCCEEDED(hr), "Failed to set src blend, hr %#x.\n", hr);
11815 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
11816 ok(SUCCEEDED(hr), "Failed to set dest blend, hr %#x.\n", hr);
11818 viewport_set_background(device, viewport, red_background);
11819 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11820 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
11821 hr = IDirect3DDevice2_BeginScene(device);
11822 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11823 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, green_quad, 4, 0);
11824 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11825 hr = IDirect3DDevice2_EndScene(device);
11826 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11827 color = get_surface_color(offscreen, 320, 240);
11828 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
11830 viewport_set_background(device, viewport, green_background);
11831 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11832 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
11833 hr = IDirect3DDevice2_BeginScene(device);
11834 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11835 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, red_quad, 4, 0);
11836 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11837 hr = IDirect3DDevice2_EndScene(device);
11838 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11839 color = get_surface_color(offscreen, 320, 240);
11840 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
11842 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
11843 ok(SUCCEEDED(hr), "Failed to disable blending, hr %#x.\n", hr);
11845 viewport_set_background(device, viewport, red_background);
11846 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11847 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
11848 hr = IDirect3DDevice2_BeginScene(device);
11849 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11850 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, green_quad, 4, 0);
11851 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11852 hr = IDirect3DDevice2_EndScene(device);
11853 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11854 color = get_surface_color(offscreen, 320, 240);
11855 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
11857 viewport_set_background(device, viewport, green_background);
11858 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11859 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
11860 hr = IDirect3DDevice2_BeginScene(device);
11861 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11862 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, red_quad, 4, 0);
11863 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11864 hr = IDirect3DDevice2_EndScene(device);
11865 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11866 color = get_surface_color(offscreen, 320, 240);
11867 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
11869 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_EDGEANTIALIAS, TRUE);
11870 ok(SUCCEEDED(hr), "Failed to enable edge antialiasing, hr %#x.\n", hr);
11872 viewport_set_background(device, viewport, red_background);
11873 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11874 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
11875 hr = IDirect3DDevice2_BeginScene(device);
11876 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11877 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, green_quad, 4, 0);
11878 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11879 hr = IDirect3DDevice2_EndScene(device);
11880 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11881 color = get_surface_color(offscreen, 320, 240);
11882 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
11884 viewport_set_background(device, viewport, green_background);
11885 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11886 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
11887 hr = IDirect3DDevice2_BeginScene(device);
11888 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11889 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, red_quad, 4, 0);
11890 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11891 hr = IDirect3DDevice2_EndScene(device);
11892 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11893 color = get_surface_color(offscreen, 320, 240);
11894 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
11896 IDirectDrawSurface_Release(offscreen);
11897 destroy_viewport(device, viewport);
11898 destroy_material(red_background);
11899 destroy_material(green_background);
11900 refcount = IDirect3DDevice2_Release(device);
11901 ok(!refcount, "Device has %u references left.\n", refcount);
11902 IDirectDraw2_Release(ddraw);
11903 DestroyWindow(window);
11906 /* TransformVertices always writes 32 bytes regardless of the input / output stride.
11907 * The stride is honored for navigating to the next vertex. 3 floats input position
11908 * are read, and 16 bytes extra vertex data are copied around. */
11909 struct transform_input
11911 float x, y, z, unused1; /* Position data, transformed. */
11912 DWORD v1, v2, v3, v4; /* Extra data, e.g. color and texture coords, copied. */
11913 DWORD unused2;
11916 struct transform_output
11918 float x, y, z, w;
11919 DWORD v1, v2, v3, v4;
11920 DWORD unused3, unused4;
11923 static void test_transform_vertices(void)
11925 IDirect3DDevice2 *device;
11926 IDirectDrawSurface *rt;
11927 IDirectDraw2 *ddraw;
11928 ULONG refcount;
11929 HWND window;
11930 HRESULT hr;
11931 D3DCOLOR color;
11932 IDirect3DViewport2 *viewport;
11933 IDirect3DMaterial2 *background;
11934 D3DMATERIAL mat;
11935 static struct transform_input position_tests[] =
11937 { 0.0f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
11938 { 1.0f, 1.0f, 1.0f, 8.0f, 6, 7, 8, 9, 10},
11939 {-1.0f, -1.0f, -1.0f, 4.0f, 11, 12, 13, 14, 15},
11940 { 0.5f, 0.5f, 0.5f, 2.0f, 16, 17, 18, 19, 20},
11941 {-0.5f, -0.5f, -0.5f, 1.0f, ~1U, ~2U, ~3U, ~4U, ~5U},
11942 {-0.5f, -0.5f, 0.0f, 0.0f, ~6U, ~7U, ~8U, ~9U, ~0U},
11944 static struct transform_input cliptest[] =
11946 { 25.59f, 25.59f, 1.0f, 0.0f, 1, 2, 3, 4, 5},
11947 { 25.61f, 25.61f, 1.01f, 0.0f, 1, 2, 3, 4, 5},
11948 {-25.59f, -25.59f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
11949 {-25.61f, -25.61f, -0.01f, 0.0f, 1, 2, 3, 4, 5},
11951 static struct transform_input offscreentest[] =
11953 {128.1f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
11955 struct transform_output out[ARRAY_SIZE(position_tests)];
11956 D3DHVERTEX out_h[ARRAY_SIZE(position_tests)];
11957 D3DTRANSFORMDATA transformdata;
11958 static const D3DVIEWPORT vp_template =
11960 sizeof(vp_template), 0, 0, 256, 256, 5.0f, 5.0f, 256.0f, 256.0f, -25.0f, 60.0f
11962 D3DVIEWPORT vp_data =
11964 sizeof(vp_data), 0, 0, 256, 256, 1.0f, 1.0f, 256.0f, 256.0f, 0.0f, 1.0f
11966 D3DVIEWPORT2 vp2_data;
11967 unsigned int i;
11968 DWORD offscreen;
11969 static D3DMATRIX mat_scale =
11971 2.0f, 0.0f, 0.0f, 0.0f,
11972 0.0f, 2.0f, 0.0f, 0.0f,
11973 0.0f, 0.0f, 2.0f, 0.0f,
11974 0.0f, 0.0f, 0.0f, 1.0f,
11976 mat_translate1 =
11978 1.0f, 0.0f, 0.0f, 0.0f,
11979 0.0f, 1.0f, 0.0f, 0.0f,
11980 0.0f, 0.0f, 1.0f, 0.0f,
11981 1.0f, 0.0f, 0.0f, 1.0f,
11983 mat_translate2 =
11985 1.0f, 0.0f, 0.0f, 0.0f,
11986 0.0f, 1.0f, 0.0f, 0.0f,
11987 0.0f, 0.0f, 1.0f, 0.0f,
11988 0.0f, 1.0f, 0.0f, 1.0f,
11990 mat_transform3 =
11992 1.0f, 0.0f, 0.0f, 0.0f,
11993 0.0f, 1.0f, 0.0f, 0.0f,
11994 0.0f, 0.0f, 1.0f, 0.0f,
11995 0.0f, 19.2f, 0.0f, 2.0f,
11997 mat_identity =
11999 1.0f, 0.0f, 0.0f, 0.0f,
12000 0.0f, 1.0f, 0.0f, 0.0f,
12001 0.0f, 0.0f, 1.0f, 0.0f,
12002 0.0f, 0.0f, 0.0f, 1.0f,
12004 static D3DLVERTEX quad[] =
12006 {{-0.75f},{-0.5f }, {0.0f}, 0, {0xffff0000}},
12007 {{-0.75f},{ 0.25f}, {0.0f}, 0, {0xffff0000}},
12008 {{ 0.5f}, {-0.5f }, {0.0f}, 0, {0xffff0000}},
12009 {{ 0.5f}, { 0.25f}, {0.0f}, 0, {0xffff0000}},
12011 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
12014 for (i = 0; i < ARRAY_SIZE(out); ++i)
12016 out[i].unused3 = 0xdeadbeef;
12017 out[i].unused4 = 0xcafecafe;
12020 window = create_window();
12021 ddraw = create_ddraw();
12022 ok(!!ddraw, "Failed to create a ddraw object.\n");
12023 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
12025 skip("Failed to create a 3D device, skipping test.\n");
12026 IDirectDraw2_Release(ddraw);
12027 DestroyWindow(window);
12028 return;
12030 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
12031 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
12033 viewport = create_viewport(device, 0, 0, 256, 256);
12034 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12035 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12037 memset(&transformdata, 0, sizeof(transformdata));
12038 transformdata.dwSize = sizeof(transformdata);
12039 transformdata.lpIn = position_tests;
12040 transformdata.dwInSize = sizeof(position_tests[0]);
12041 transformdata.lpOut = out;
12042 transformdata.dwOutSize = sizeof(out[0]);
12043 transformdata.lpHOut = NULL;
12045 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12046 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12047 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12048 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12050 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12052 static const struct vec4 cmp[] =
12054 {128.0f, 128.0f, 0.0f, 1.0f}, {129.0f, 127.0f, 1.0f, 1.0f}, {127.0f, 129.0f, -1.0f, 1.0f},
12055 {128.5f, 127.5f, 0.5f, 1.0f}, {127.5f, 128.5f, -0.5f, 1.0f}, {127.5f, 128.5f, 0.0f, 1.0f}
12058 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12059 "Vertex %u differs. Got %f %f %f %f.\n", i,
12060 out[i].x, out[i].y, out[i].z, out[i].w);
12061 ok(out[i].v1 == position_tests[i].v1 && out[i].v2 == position_tests[i].v2
12062 && out[i].v3 == position_tests[i].v3 && out[i].v4 == position_tests[i].v4,
12063 "Vertex %u payload is %u %u %u %u.\n", i, out[i].v1, out[i].v2, out[i].v3, out[i].v4);
12064 ok(out[i].unused3 == 0xdeadbeef && out[i].unused4 == 0xcafecafe,
12065 "Vertex %u unused data is %#x, %#x.\n", i, out[i].unused3, out[i].unused4);
12068 vp_data = vp_template;
12069 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12070 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12071 offscreen = 0xdeadbeef;
12072 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12073 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12074 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12075 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12077 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12079 static const struct vec4 cmp[] =
12081 {128.0f, 128.0f, 0.0f, 1.0f}, {133.0f, 123.0f, 1.0f, 1.0f}, {123.0f, 133.0f, -1.0f, 1.0f},
12082 {130.5f, 125.5f, 0.5f, 1.0f}, {125.5f, 130.5f, -0.5f, 1.0f}, {125.5f, 130.5f, 0.0f, 1.0f}
12084 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12085 "Vertex %u differs. Got %f %f %f %f.\n", i,
12086 out[i].x, out[i].y, out[i].z, out[i].w);
12089 vp_data.dwX = 10;
12090 vp_data.dwY = 20;
12091 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12092 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12093 offscreen = 0xdeadbeef;
12094 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12095 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12096 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12097 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12098 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12100 static const struct vec4 cmp[] =
12102 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, {133.0f, 153.0f, -1.0f, 1.0f},
12103 {140.5f, 145.5f, 0.5f, 1.0f}, {135.5f, 150.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
12105 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12106 "Vertex %u differs. Got %f %f %f %f.\n", i,
12107 out[i].x, out[i].y, out[i].z, out[i].w);
12110 transformdata.lpHOut = out_h;
12111 offscreen = 0xdeadbeef;
12112 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12113 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12114 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12115 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12116 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12118 static const D3DHVERTEX cmp_h[] =
12120 {0, { 0.0f}, { 0.0f}, { 0.0f}}, {0, { 1.0f}, { 1.0f}, {1.0f}},
12121 {D3DCLIP_FRONT, {-1.0f}, {-1.0f}, {-1.0f}}, {0, { 0.5f}, { 0.5f}, {0.5f}},
12122 {D3DCLIP_FRONT, {-0.5f}, {-0.5f}, {-0.5f}}, {0, {-0.5f}, {-0.5f}, {0.0f}}
12124 ok(compare_float(U1(cmp_h[i]).hx, U1(out_h[i]).hx, 4096)
12125 && compare_float(U2(cmp_h[i]).hy, U2(out_h[i]).hy, 4096)
12126 && compare_float(U3(cmp_h[i]).hz, U3(out_h[i]).hz, 4096)
12127 && cmp_h[i].dwFlags == out_h[i].dwFlags,
12128 "HVertex %u differs. Got %#x %f %f %f.\n", i,
12129 out_h[i].dwFlags, U1(out_h[i]).hx, U2(out_h[i]).hy, U3(out_h[i]).hz);
12131 /* No scheme has been found behind those return values. It seems to be
12132 * whatever data windows has when throwing the vertex away. Modify the
12133 * input test vertices to test this more. Depending on the input data
12134 * it can happen that the z coord gets written into y, or similar things. */
12135 if (0)
12137 static const struct vec4 cmp[] =
12139 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, { -1.0f, -1.0f, 0.5f, 1.0f},
12140 {140.5f, 145.5f, 0.5f, 1.0f}, { -0.5f, -0.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
12142 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12143 "Vertex %u differs. Got %f %f %f %f.\n", i,
12144 out[i].x, out[i].y, out[i].z, out[i].w);
12148 transformdata.lpIn = cliptest;
12149 transformdata.dwInSize = sizeof(cliptest[0]);
12150 offscreen = 0xdeadbeef;
12151 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12152 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12153 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12154 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12155 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12157 static const DWORD flags[] =
12160 D3DCLIP_RIGHT | D3DCLIP_BACK | D3DCLIP_TOP,
12162 D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
12164 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
12167 vp_data = vp_template;
12168 vp_data.dwWidth = 10;
12169 vp_data.dwHeight = 480;
12170 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12171 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12172 offscreen = 0xdeadbeef;
12173 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12174 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12175 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12176 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12177 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12179 static const DWORD flags[] =
12181 D3DCLIP_RIGHT,
12182 D3DCLIP_RIGHT | D3DCLIP_BACK,
12183 D3DCLIP_LEFT,
12184 D3DCLIP_LEFT | D3DCLIP_FRONT,
12186 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
12189 vp_data = vp_template;
12190 vp_data.dwWidth = 256;
12191 vp_data.dwHeight = 256;
12192 vp_data.dvScaleX = 1;
12193 vp_data.dvScaleY = 1;
12194 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12195 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12196 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12197 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12198 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12199 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12200 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12202 static const DWORD flags[] =
12205 D3DCLIP_BACK,
12207 D3DCLIP_FRONT,
12209 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#x.\n", i, out_h[i].dwFlags);
12212 /* Finally try to figure out how the DWORD dwOffscreen works.
12213 * It is a logical AND of the vertices' dwFlags members. */
12214 vp_data = vp_template;
12215 vp_data.dwWidth = 5;
12216 vp_data.dwHeight = 5;
12217 vp_data.dvScaleX = 10000.0f;
12218 vp_data.dvScaleY = 10000.0f;
12219 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12220 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12221 transformdata.lpIn = cliptest;
12222 offscreen = 0xdeadbeef;
12223 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12224 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12225 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12226 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12228 offscreen = 0xdeadbeef;
12229 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12230 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12231 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12232 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
12233 offscreen = 0xdeadbeef;
12234 hr = IDirect3DViewport2_TransformVertices(viewport, 2,
12235 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12236 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12237 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
12238 hr = IDirect3DViewport2_TransformVertices(viewport, 3,
12239 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12240 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12241 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12243 transformdata.lpIn = cliptest + 1;
12244 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12245 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12246 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12247 ok(offscreen == (D3DCLIP_BACK | D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %x.\n", offscreen);
12249 transformdata.lpIn = cliptest + 2;
12250 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12251 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12252 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12253 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
12254 offscreen = 0xdeadbeef;
12255 hr = IDirect3DViewport2_TransformVertices(viewport, 2,
12256 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12257 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12258 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
12260 transformdata.lpIn = cliptest + 3;
12261 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12262 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12263 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12264 ok(offscreen == (D3DCLIP_FRONT | D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %x.\n", offscreen);
12266 transformdata.lpIn = offscreentest;
12267 transformdata.dwInSize = sizeof(offscreentest[0]);
12268 vp_data = vp_template;
12269 vp_data.dwWidth = 257;
12270 vp_data.dwHeight = 257;
12271 vp_data.dvScaleX = 1.0f;
12272 vp_data.dvScaleY = 1.0f;
12273 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12274 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12275 offscreen = 0xdeadbeef;
12276 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12277 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12278 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12279 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12281 vp_data.dwWidth = 256;
12282 vp_data.dwHeight = 256;
12283 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12284 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12285 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12286 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12287 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12288 ok(offscreen == D3DCLIP_RIGHT, "Offscreen is %x.\n", offscreen);
12290 /* Test the effect of Matrices.
12292 * Basically the x coordinate ends up as ((x + 1) * 2 + 0) * 5 and
12293 * y as ((y + 0) * 2 + 1) * 5. The 5 comes from dvScaleX/Y, 2 from
12294 * the view matrix and the +1's from the world and projection matrix. */
12295 vp_data.dwX = 0;
12296 vp_data.dwY = 0;
12297 vp_data.dwWidth = 256;
12298 vp_data.dwHeight = 256;
12299 vp_data.dvScaleX = 5.0f;
12300 vp_data.dvScaleY = 5.0f;
12301 vp_data.dvMinZ = 0.0f;
12302 vp_data.dvMaxZ = 1.0f;
12303 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12304 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12306 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat_translate1);
12307 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12308 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat_scale);
12309 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12310 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat_translate2);
12311 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12313 transformdata.lpIn = position_tests;
12314 transformdata.dwInSize = sizeof(position_tests[0]);
12315 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12316 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12317 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12319 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12321 static const struct vec4 cmp[] =
12323 {138.0f, 123.0f, 0.0f, 1.0f}, {148.0f, 113.0f, 2.0f, 1.0f}, {128.0f, 133.0f, -2.0f, 1.0f},
12324 {143.0f, 118.0f, 1.0f, 1.0f}, {133.0f, 128.0f, -1.0f, 1.0f}, {133.0f, 128.0f, 0.0f, 1.0f}
12327 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12328 "Vertex %u differs. Got %f %f %f %f.\n", i,
12329 out[i].x, out[i].y, out[i].z, out[i].w);
12332 /* Invalid flags. */
12333 offscreen = 0xdeadbeef;
12334 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12335 &transformdata, 0, &offscreen);
12336 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12337 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
12339 /* NULL transform data. */
12340 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12341 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
12342 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12343 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
12344 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12345 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
12346 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12347 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
12349 /* NULL transform data and NULL dwOffscreen.
12351 * Valid transform data + NULL dwOffscreen -> crash. */
12352 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12353 NULL, D3DTRANSFORM_UNCLIPPED, NULL);
12354 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12356 /* No vertices. */
12357 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12358 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12359 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12360 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12361 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12362 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12363 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12364 ok(offscreen == ~0U, "Offscreen is %x.\n", offscreen);
12366 /* Invalid sizes. */
12367 offscreen = 0xdeadbeef;
12368 transformdata.dwSize = sizeof(transformdata) - 1;
12369 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12370 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12371 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12372 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
12373 transformdata.dwSize = sizeof(transformdata) + 1;
12374 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
12375 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12376 ok(hr == DDERR_INVALIDPARAMS, "TransformVertices returned %#x.\n", hr);
12377 ok(offscreen == 0xdeadbeef, "Offscreen is %x.\n", offscreen);
12379 /* NULL lpIn or lpOut -> crash, except when transforming 0 vertices. */
12380 transformdata.dwSize = sizeof(transformdata);
12381 transformdata.lpIn = NULL;
12382 transformdata.lpOut = NULL;
12383 offscreen = 0xdeadbeef;
12384 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
12385 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12386 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12387 ok(offscreen == ~0U, "Offscreen is %x.\n", offscreen);
12389 /* Test how vertices are transformed during draws. */
12390 vp_data.dwX = 20;
12391 vp_data.dwY = 20;
12392 vp_data.dwWidth = 200;
12393 vp_data.dwHeight = 400;
12394 vp_data.dvScaleX = 20.0f;
12395 vp_data.dvScaleY = 50.0f;
12396 vp_data.dvMinZ = 0.0f;
12397 vp_data.dvMaxZ = 1.0f;
12398 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
12399 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
12400 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
12401 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
12403 ok(SUCCEEDED(hr), "Failed to clear the render target, hr %#x.\n", hr);
12404 background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 0.0f);
12405 viewport_set_background(device, viewport, background);
12406 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
12407 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12409 hr = IDirect3DDevice2_BeginScene(device);
12410 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12411 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
12412 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12413 hr = IDirect3DDevice2_EndScene(device);
12414 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12416 color = get_surface_color(rt, 128, 143);
12417 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12418 color = get_surface_color(rt, 132, 143);
12419 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12420 color = get_surface_color(rt, 128, 147);
12421 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12422 color = get_surface_color(rt, 132, 147);
12423 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12425 color = get_surface_color(rt, 177, 217);
12426 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12427 color = get_surface_color(rt, 181, 217);
12428 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12429 color = get_surface_color(rt, 177, 221);
12430 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12431 color = get_surface_color(rt, 181, 221);
12432 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12434 /* Test D3DVIEWPORT2 behavior. */
12435 vp2_data.dwSize = sizeof(vp2_data);
12436 vp2_data.dwX = 20;
12437 vp2_data.dwY = 20;
12438 vp2_data.dwWidth = 200;
12439 vp2_data.dwHeight = 400;
12440 vp2_data.dvClipX = -0.5f;
12441 vp2_data.dvClipY = 4.0f;
12442 vp2_data.dvClipWidth = 5.0f;
12443 vp2_data.dvClipHeight = 10.0f;
12444 vp2_data.dvMinZ = 0.0f;
12445 vp2_data.dvMaxZ = 2.0f;
12446 hr = IDirect3DViewport2_SetViewport2(viewport, &vp2_data);
12447 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
12448 transformdata.lpIn = position_tests;
12449 transformdata.lpOut = out;
12450 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
12451 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
12452 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12453 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
12455 static const struct vec4 cmp[] =
12457 {120.0f, 140.0f, 0.0f, 1.0f}, {200.0f, 60.0f, 1.0f, 1.0f}, {40.0f, 220.0f, -1.0f, 1.0f},
12458 {160.0f, 100.0f, 0.5f, 1.0f}, { 80.0f, 180.0f, -0.5f, 1.0f}, {80.0f, 180.0f, 0.0f, 1.0f}
12461 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
12462 "Vertex %u differs. Got %f %f %f %f.\n", i,
12463 out[i].x, out[i].y, out[i].z, out[i].w);
12466 memset(&mat, 0, sizeof(mat));
12467 mat.dwSize = sizeof(mat);
12468 U1(U(mat).diffuse).r = 0.0f;
12469 U2(U(mat).diffuse).g = 1.0f;
12470 U3(U(mat).diffuse).b = 0.0f;
12471 U4(U(mat).diffuse).a = 0.0f;
12472 hr = IDirect3DMaterial2_SetMaterial(background, &mat);
12473 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
12474 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
12475 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
12477 hr = IDirect3DDevice2_BeginScene(device);
12478 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12479 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
12480 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12481 hr = IDirect3DDevice2_EndScene(device);
12482 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12484 color = get_surface_color(rt, 58, 118);
12485 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12486 color = get_surface_color(rt, 62, 118);
12487 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12488 color = get_surface_color(rt, 58, 122);
12489 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12490 color = get_surface_color(rt, 62, 122);
12491 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12493 color = get_surface_color(rt, 157, 177);
12494 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12495 color = get_surface_color(rt, 161, 177);
12496 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12497 color = get_surface_color(rt, 157, 181);
12498 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12499 color = get_surface_color(rt, 161, 181);
12500 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12502 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat_identity);
12503 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12504 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat_identity);
12505 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12506 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat_transform3);
12507 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12509 vp2_data.dwX = 0.0;
12510 vp2_data.dwY = 0.0;
12511 vp2_data.dwWidth = 1;
12512 vp2_data.dwHeight = 1;
12513 vp2_data.dvClipX = -12.8f;
12514 vp2_data.dvClipY = 12.8f + mat_transform3._42 / mat_transform3._44;
12515 vp2_data.dvClipWidth = 25.6f;
12516 vp2_data.dvClipHeight = 25.6f;
12517 vp2_data.dvMinZ = 0.0f;
12518 vp2_data.dvMaxZ = 0.5f;
12519 hr = IDirect3DViewport2_SetViewport2(viewport, &vp2_data);
12520 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
12521 transformdata.lpIn = cliptest;
12522 transformdata.dwInSize = sizeof(cliptest[0]);
12523 offscreen = 0xdeadbeef;
12524 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
12525 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
12526 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#x.\n", hr);
12527 ok(!offscreen, "Offscreen is %x.\n", offscreen);
12528 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
12530 static const D3DHVERTEX cmp_h[] =
12532 {0, { 25.59f}, { 44.79f}, { 1.0f }},
12533 {D3DCLIP_RIGHT | D3DCLIP_TOP | D3DCLIP_BACK, { 25.61f}, { 44.81f}, { 1.01f}},
12534 {0, {-25.59f}, {-6.39f }, { 0.0f }},
12535 {D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,{-25.61f}, {-6.41f }, {-0.01f}},
12537 ok(compare_float(U1(cmp_h[i]).hx, U1(out_h[i]).hx, 4096)
12538 && compare_float(U2(cmp_h[i]).hy, U2(out_h[i]).hy, 4096)
12539 && compare_float(U3(cmp_h[i]).hz, U3(out_h[i]).hz, 4096)
12540 && cmp_h[i].dwFlags == out_h[i].dwFlags,
12541 "HVertex %u differs. Got %#x %f %f %f.\n", i,
12542 out_h[i].dwFlags, U1(out_h[i]).hx, U2(out_h[i]).hy, U3(out_h[i]).hz);
12545 IDirectDrawSurface_Release(rt);
12546 destroy_viewport(device, viewport);
12547 IDirect3DMaterial2_Release(background);
12548 refcount = IDirect3DDevice_Release(device);
12549 ok(!refcount, "Device has %u references left.\n", refcount);
12550 IDirectDraw2_Release(ddraw);
12551 DestroyWindow(window);
12554 static void test_display_mode_surface_pixel_format(void)
12556 unsigned int width, height, bpp;
12557 IDirectDrawSurface *surface;
12558 DDSURFACEDESC surface_desc;
12559 IDirectDraw2 *ddraw;
12560 ULONG refcount;
12561 HWND window;
12562 HRESULT hr;
12564 if (!(ddraw = create_ddraw()))
12566 skip("Failed to create ddraw.\n");
12567 return;
12570 surface_desc.dwSize = sizeof(surface_desc);
12571 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
12572 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
12573 width = surface_desc.dwWidth;
12574 height = surface_desc.dwHeight;
12576 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
12577 0, 0, width, height, NULL, NULL, NULL, NULL);
12578 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
12579 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12581 bpp = 0;
12582 if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 16, 0, 0)))
12583 bpp = 16;
12584 if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 24, 0, 0)))
12585 bpp = 24;
12586 if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
12587 bpp = 32;
12588 ok(bpp, "Set display mode failed.\n");
12590 surface_desc.dwSize = sizeof(surface_desc);
12591 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
12592 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
12593 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
12594 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
12595 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
12596 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, bpp);
12598 memset(&surface_desc, 0, sizeof(surface_desc));
12599 surface_desc.dwSize = sizeof(surface_desc);
12600 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
12601 surface_desc.dwBackBufferCount = 1;
12602 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
12603 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12604 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
12605 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
12606 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
12607 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
12608 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
12609 ok(surface_desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
12610 surface_desc.ddpfPixelFormat.dwFlags);
12611 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
12612 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, bpp);
12613 IDirectDrawSurface_Release(surface);
12615 memset(&surface_desc, 0, sizeof(surface_desc));
12616 surface_desc.dwSize = sizeof(surface_desc);
12617 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
12618 surface_desc.dwWidth = width;
12619 surface_desc.dwHeight = height;
12620 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12621 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12622 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
12623 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
12624 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
12625 ok(surface_desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
12626 surface_desc.ddpfPixelFormat.dwFlags);
12627 ok(U1(surface_desc.ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
12628 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, bpp);
12629 IDirectDrawSurface_Release(surface);
12631 refcount = IDirectDraw2_Release(ddraw);
12632 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
12633 DestroyWindow(window);
12636 static void test_surface_desc_size(void)
12638 union
12640 DWORD dwSize;
12641 DDSURFACEDESC desc1;
12642 DDSURFACEDESC2 desc2;
12643 BYTE blob[1024];
12644 } desc;
12645 IDirectDrawSurface7 *surface7;
12646 IDirectDrawSurface2 *surface2;
12647 IDirectDrawSurface *surface;
12648 DDSURFACEDESC surface_desc;
12649 HRESULT expected_hr, hr;
12650 IDirectDraw2 *ddraw;
12651 unsigned int i, j;
12652 ULONG refcount;
12654 static const struct
12656 unsigned int caps;
12657 const char *name;
12659 surface_caps[] =
12661 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
12662 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
12663 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
12665 static const unsigned int desc_sizes[] =
12667 sizeof(DDSURFACEDESC),
12668 sizeof(DDSURFACEDESC2),
12669 sizeof(DDSURFACEDESC) + 1,
12670 sizeof(DDSURFACEDESC2) + 1,
12671 2 * sizeof(DDSURFACEDESC),
12672 2 * sizeof(DDSURFACEDESC2),
12673 sizeof(DDSURFACEDESC) - 1,
12674 sizeof(DDSURFACEDESC2) - 1,
12675 sizeof(DDSURFACEDESC) / 2,
12676 sizeof(DDSURFACEDESC2) / 2,
12680 sizeof(desc) / 2,
12681 sizeof(desc) - 100,
12684 if (!(ddraw = create_ddraw()))
12686 skip("Failed to create ddraw.\n");
12687 return;
12689 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
12690 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12692 for (i = 0; i < ARRAY_SIZE(surface_caps); ++i)
12694 memset(&surface_desc, 0, sizeof(surface_desc));
12695 surface_desc.dwSize = sizeof(surface_desc);
12696 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
12697 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
12698 surface_desc.dwHeight = 128;
12699 surface_desc.dwWidth = 128;
12700 if (FAILED(IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
12702 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
12703 continue;
12705 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface2, (void **)&surface2);
12706 ok(hr == DD_OK, "Failed to query IDirectDrawSurface2, hr %#x, type %s.\n", hr, surface_caps[i].name);
12707 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface7, (void **)&surface7);
12708 ok(hr == DD_OK, "Failed to query IDirectDrawSurface7, hr %#x, type %s.\n", hr, surface_caps[i].name);
12710 /* GetSurfaceDesc() */
12711 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
12713 memset(&desc, 0, sizeof(desc));
12714 desc.dwSize = desc_sizes[j];
12715 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
12716 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
12717 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12718 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12720 memset(&desc, 0, sizeof(desc));
12721 desc.dwSize = desc_sizes[j];
12722 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
12723 hr = IDirectDrawSurface2_GetSurfaceDesc(surface2, &desc.desc1);
12724 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12725 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12727 memset(&desc, 0, sizeof(desc));
12728 desc.dwSize = desc_sizes[j];
12729 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
12730 hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
12731 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12732 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12735 /* Lock() */
12736 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
12738 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
12739 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
12740 DWORD expected_texture_stage;
12742 memset(&desc, 0, sizeof(desc));
12743 desc.dwSize = desc_sizes[j];
12744 desc.desc2.dwTextureStage = 0xdeadbeef;
12745 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
12746 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
12747 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
12748 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12749 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12750 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
12751 desc_sizes[j], desc.dwSize, surface_caps[i].name);
12752 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
12753 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
12754 if (SUCCEEDED(hr))
12756 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
12757 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
12758 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
12759 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
12760 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
12761 todo_wine_if(!expected_texture_stage)
12762 ok(desc.desc2.dwTextureStage == expected_texture_stage,
12763 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
12764 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
12765 IDirectDrawSurface_Unlock(surface, NULL);
12768 memset(&desc, 0, sizeof(desc));
12769 desc.dwSize = desc_sizes[j];
12770 desc.desc2.dwTextureStage = 0xdeadbeef;
12771 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
12772 hr = IDirectDrawSurface2_Lock(surface2, NULL, &desc.desc1, 0, 0);
12773 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
12774 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12775 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12776 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
12777 desc_sizes[j], desc.dwSize, surface_caps[i].name);
12778 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
12779 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
12780 if (SUCCEEDED(hr))
12782 ok(desc.desc2.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
12783 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
12784 ok(desc.desc2.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
12785 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
12786 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
12787 todo_wine_if(!expected_texture_stage)
12788 ok(desc.desc2.dwTextureStage == expected_texture_stage,
12789 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
12790 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
12791 IDirectDrawSurface2_Unlock(surface2, NULL);
12794 memset(&desc, 0, sizeof(desc));
12795 desc.dwSize = desc_sizes[j];
12796 desc.desc2.dwTextureStage = 0xdeadbeef;
12797 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
12798 hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
12799 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
12800 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12801 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12802 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
12803 desc_sizes[j], desc.dwSize, surface_caps[i].name);
12804 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
12805 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
12806 if (SUCCEEDED(hr))
12808 ok(desc.desc2.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
12809 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
12810 ok(desc.desc2.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
12811 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
12812 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
12813 ok(desc.desc2.dwTextureStage == expected_texture_stage,
12814 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
12815 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
12816 IDirectDrawSurface7_Unlock(surface7, NULL);
12820 IDirectDrawSurface7_Release(surface7);
12821 IDirectDrawSurface2_Release(surface2);
12822 IDirectDrawSurface_Release(surface);
12825 /* GetDisplayMode() */
12826 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
12828 memset(&desc, 0xcc, sizeof(desc));
12829 desc.dwSize = desc_sizes[j];
12830 expected_hr = (desc.dwSize == sizeof(DDSURFACEDESC) || desc.dwSize == sizeof(DDSURFACEDESC2))
12831 ? DD_OK : DDERR_INVALIDPARAMS;
12832 hr = IDirectDraw2_GetDisplayMode(ddraw, &desc.desc1);
12833 ok(hr == expected_hr, "Got hr %#x, expected %#x, size %u.\n", hr, expected_hr, desc_sizes[j]);
12834 if (SUCCEEDED(hr))
12836 ok(desc.dwSize == sizeof(DDSURFACEDESC), "Wrong size %u for %u.\n", desc.dwSize, desc_sizes[j]);
12837 ok(desc.blob[desc_sizes[j]] == 0xcc, "Overflow for size %u.\n", desc_sizes[j]);
12838 ok(desc.blob[desc_sizes[j] - 1] != 0xcc, "Struct not cleared for size %u.\n", desc_sizes[j]);
12842 refcount = IDirectDraw2_Release(ddraw);
12843 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
12846 static void test_ck_operation(void)
12848 IDirectDrawSurface2 *src, *dst;
12849 IDirectDrawSurface7 *src7, *dst7;
12850 IDirectDrawSurface *surface1;
12851 DDSURFACEDESC surface_desc;
12852 IDirectDraw2 *ddraw;
12853 ULONG refcount;
12854 HWND window;
12855 HRESULT hr;
12856 D3DCOLOR *color;
12857 unsigned int i;
12858 DDCOLORKEY ckey;
12859 DDBLTFX fx;
12861 window = create_window();
12862 ddraw = create_ddraw();
12863 ok(!!ddraw, "Failed to create a ddraw object.\n");
12864 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12865 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12867 memset(&surface_desc, 0, sizeof(surface_desc));
12868 surface_desc.dwSize = sizeof(surface_desc);
12869 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12870 surface_desc.dwWidth = 4;
12871 surface_desc.dwHeight = 1;
12872 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12873 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
12874 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
12875 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
12876 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
12877 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
12878 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
12879 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12880 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&dst);
12881 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#x.\n", hr);
12882 IDirectDrawSurface_Release(surface1);
12884 surface_desc.dwFlags |= DDSD_CKSRCBLT;
12885 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
12886 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff;
12887 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
12888 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12889 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&src);
12890 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#x.\n", hr);
12891 IDirectDrawSurface_Release(surface1);
12893 hr = IDirectDrawSurface2_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12894 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12895 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
12896 color = surface_desc.lpSurface;
12897 color[0] = 0x77010203;
12898 color[1] = 0x00010203;
12899 color[2] = 0x77ff00ff;
12900 color[3] = 0x00ff00ff;
12901 hr = IDirectDrawSurface2_Unlock(src, NULL);
12902 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12904 for (i = 0; i < 2; ++i)
12906 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12907 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12908 color = surface_desc.lpSurface;
12909 color[0] = 0xcccccccc;
12910 color[1] = 0xcccccccc;
12911 color[2] = 0xcccccccc;
12912 color[3] = 0xcccccccc;
12913 hr = IDirectDrawSurface2_Unlock(dst, NULL);
12914 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12916 if (i)
12918 hr = IDirectDrawSurface2_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY);
12919 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12921 else
12923 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL);
12924 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12927 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL);
12928 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12929 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
12930 color = surface_desc.lpSurface;
12931 /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
12932 * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for
12933 * color keying, but do not copy it into the destination surface. Nvidia neither uses it for
12934 * color keying nor copies it. */
12935 ok((color[0] == 0x77010203 && color[1] == 0x00010203
12936 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */
12937 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
12938 && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */
12939 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
12940 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */
12941 || broken(color[0] == 0xff010203 && color[1] == 0xff010203
12942 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */,
12943 "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n",
12944 color[0], color[1], color[2], color[3], i);
12945 hr = IDirectDrawSurface2_Unlock(dst, NULL);
12946 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12949 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12950 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12951 ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff,
12952 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12954 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
12955 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12956 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12958 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12959 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12960 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12961 ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00,
12962 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12964 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
12965 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
12966 hr = IDirectDrawSurface2_GetSurfaceDesc(src, &surface_desc);
12967 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
12968 ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00
12969 && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00,
12970 "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
12971 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
12973 /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
12974 ckey.dwColorSpaceLowValue = 0x000000ff;
12975 ckey.dwColorSpaceHighValue = 0x00000000;
12976 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12977 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12979 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12980 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12981 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12982 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
12983 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12985 ckey.dwColorSpaceLowValue = 0x000000ff;
12986 ckey.dwColorSpaceHighValue = 0x00000001;
12987 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12988 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12990 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12991 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12992 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12993 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
12994 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12996 ckey.dwColorSpaceLowValue = 0x000000fe;
12997 ckey.dwColorSpaceHighValue = 0x000000fd;
12998 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12999 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13001 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13002 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13003 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13004 ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe,
13005 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13007 IDirectDrawSurface2_Release(src);
13008 IDirectDrawSurface2_Release(dst);
13010 /* Test source and destination keys and where they are read from. Use a surface with alpha
13011 * to avoid driver-dependent content in the X channel. */
13012 memset(&surface_desc, 0, sizeof(surface_desc));
13013 surface_desc.dwSize = sizeof(surface_desc);
13014 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13015 surface_desc.dwWidth = 6;
13016 surface_desc.dwHeight = 1;
13017 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13018 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
13019 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
13020 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
13021 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
13022 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
13023 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
13024 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
13025 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13026 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&dst);
13027 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#x.\n", hr);
13028 IDirectDrawSurface_Release(surface1);
13030 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
13031 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13032 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&src);
13033 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface2, hr %#x.\n", hr);
13034 IDirectDrawSurface_Release(surface1);
13036 ckey.dwColorSpaceLowValue = 0x0000ff00;
13037 ckey.dwColorSpaceHighValue = 0x0000ff00;
13038 hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
13039 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13040 ckey.dwColorSpaceLowValue = 0x00ff0000;
13041 ckey.dwColorSpaceHighValue = 0x00ff0000;
13042 hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_DESTBLT, &ckey);
13043 ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr);
13044 if (FAILED(hr))
13046 /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */
13047 skip("Failed to set destination color key, skipping related tests.\n");
13048 goto done;
13051 ckey.dwColorSpaceLowValue = 0x000000ff;
13052 ckey.dwColorSpaceHighValue = 0x000000ff;
13053 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13054 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13055 ckey.dwColorSpaceLowValue = 0x000000aa;
13056 ckey.dwColorSpaceHighValue = 0x000000aa;
13057 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_DESTBLT, &ckey);
13058 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13060 memset(&fx, 0, sizeof(fx));
13061 fx.dwSize = sizeof(fx);
13062 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000;
13063 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000;
13064 fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100;
13065 fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100;
13067 hr = IDirectDrawSurface2_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13068 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13069 color = surface_desc.lpSurface;
13070 color[0] = 0x000000ff; /* Applies to src blt key in src surface. */
13071 color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */
13072 color[2] = 0x00ff0000; /* Dst color key in dst surface. */
13073 color[3] = 0x0000ff00; /* Src color key in dst surface. */
13074 color[4] = 0x00001100; /* Src color key in ddbltfx. */
13075 color[5] = 0x00110000; /* Dst color key in ddbltfx. */
13076 hr = IDirectDrawSurface2_Unlock(src, NULL);
13077 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13079 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13080 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13081 color = surface_desc.lpSurface;
13082 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13083 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13084 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13086 /* Test a blit without keying. */
13087 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, 0, &fx);
13088 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13090 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13091 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13092 color = surface_desc.lpSurface;
13093 /* Should have copied src data unmodified to dst. */
13094 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13095 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13096 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13097 color[0], color[1], color[2], color[3], color[4], color[5]);
13099 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13100 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13101 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13103 /* Src key. */
13104 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
13105 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13107 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13108 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13109 color = surface_desc.lpSurface;
13110 /* Src key applied to color[0]. It is unmodified, the others are copied. */
13111 ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13112 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13113 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13114 color[0], color[1], color[2], color[3], color[4], color[5]);
13116 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13117 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13118 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13120 /* Src override. */
13121 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
13122 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13124 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13125 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13126 color = surface_desc.lpSurface;
13127 /* Override key applied to color[5]. It is unmodified, the others are copied. */
13128 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13129 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555,
13130 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13131 color[0], color[1], color[2], color[3], color[4], color[5]);
13133 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13134 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13135 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13137 /* Src override AND src key. That is not supposed to work. */
13138 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
13139 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13141 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13142 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13143 color = surface_desc.lpSurface;
13144 /* Ensure the destination was not changed. */
13145 ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 &&
13146 color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555,
13147 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13148 color[0], color[1], color[2], color[3], color[4], color[5]);
13150 /* Use different dst colors for the dst key test. */
13151 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13152 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13153 color[2] = 0x00001100; /* Dest key in override. */
13154 color[3] = 0x00001100; /* Dest key in override. */
13155 color[4] = 0x000000aa; /* Dest key in src surface. */
13156 color[5] = 0x000000aa; /* Dest key in src surface. */
13157 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13158 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13160 /* Dest key blit. The key is taken from the SOURCE surface in v2! */
13161 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13162 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13164 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13165 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13166 color = surface_desc.lpSurface;
13167 /* Dst key applied to color[4,5], they are the only changed pixels. */
13168 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13169 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
13170 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13171 color[0], color[1], color[2], color[3], color[4], color[5]);
13173 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13174 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13175 color[2] = 0x00001100; /* Dest key in override. */
13176 color[3] = 0x00001100; /* Dest key in override. */
13177 color[4] = 0x000000aa; /* Dest key in src surface. */
13178 color[5] = 0x000000aa; /* Dest key in src surface. */
13179 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13180 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13182 /* What happens with a QI'd newer version of the interface? It takes the key
13183 * from the destination surface. */
13184 hr = IDirectDrawSurface2_QueryInterface(src, &IID_IDirectDrawSurface7, (void **)&src7);
13185 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13186 hr = IDirectDrawSurface2_QueryInterface(dst, &IID_IDirectDrawSurface7, (void **)&dst7);
13187 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13189 hr = IDirectDrawSurface7_Blt(dst7, NULL, src7, NULL, DDBLT_KEYDEST, &fx);
13190 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13192 IDirectDrawSurface7_Release(dst7);
13193 IDirectDrawSurface7_Release(src7);
13195 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13196 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13197 color = surface_desc.lpSurface;
13198 /* Dst key applied to color[0,1], they are the only changed pixels. */
13199 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
13200 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13201 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13202 color[0], color[1], color[2], color[3], color[4], color[5]);
13204 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13205 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13206 color[2] = 0x00001100; /* Dest key in override. */
13207 color[3] = 0x00001100; /* Dest key in override. */
13208 color[4] = 0x000000aa; /* Dest key in src surface. */
13209 color[5] = 0x000000aa; /* Dest key in src surface. */
13210 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13211 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13213 /* Dest override key blit. */
13214 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
13215 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13217 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13218 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13219 color = surface_desc.lpSurface;
13220 /* Dst key applied to color[2,3], they are the only changed pixels. */
13221 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 &&
13222 color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13223 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13224 color[0], color[1], color[2], color[3], color[4], color[5]);
13226 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13227 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13228 color[2] = 0x00001100; /* Dest key in override. */
13229 color[3] = 0x00001100; /* Dest key in override. */
13230 color[4] = 0x000000aa; /* Dest key in src surface. */
13231 color[5] = 0x000000aa; /* Dest key in src surface. */
13232 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13233 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13235 /* Dest override together with surface key. Supposed to fail. */
13236 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
13237 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13239 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13240 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13241 color = surface_desc.lpSurface;
13242 /* Destination is unchanged. */
13243 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13244 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13245 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13246 color[0], color[1], color[2], color[3], color[4], color[5]);
13247 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13248 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13250 /* Source and destination key. This is driver dependent. New HW treats it like
13251 * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */
13252 if (0)
13254 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
13255 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13257 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13258 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13259 color = surface_desc.lpSurface;
13260 /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if
13261 * the driver applies it. */
13262 ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13263 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13264 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13265 color[0], color[1], color[2], color[3], color[4], color[5]);
13267 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13268 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13269 color[2] = 0x00001100; /* Dest key in override. */
13270 color[3] = 0x00001100; /* Dest key in override. */
13271 color[4] = 0x000000aa; /* Dest key in src surface. */
13272 color[5] = 0x000000aa; /* Dest key in src surface. */
13273 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13274 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13277 /* Override keys without ddbltfx parameter fail */
13278 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
13279 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13280 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
13281 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13283 /* Try blitting without keys in the source surface. */
13284 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_SRCBLT, NULL);
13285 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13286 hr = IDirectDrawSurface2_SetColorKey(src, DDCKEY_DESTBLT, NULL);
13287 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13289 /* That fails now. Do not bother to check that the data is unmodified. */
13290 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
13291 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13293 /* Surprisingly this still works. It uses the old key from the src surface. */
13294 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13295 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13297 hr = IDirectDrawSurface2_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13298 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13299 color = surface_desc.lpSurface;
13300 /* Dst key applied to color[4,5], they are the only changed pixels. */
13301 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13302 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
13303 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13304 color[0], color[1], color[2], color[3], color[4], color[5]);
13305 hr = IDirectDrawSurface2_Unlock(dst, NULL);
13306 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13308 /* This returns DDERR_NOCOLORKEY as expected. */
13309 hr = IDirectDrawSurface2_GetColorKey(src, DDCKEY_DESTBLT, &ckey);
13310 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
13312 /* GetSurfaceDesc returns a zeroed key as expected. */
13313 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x12345678;
13314 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x12345678;
13315 hr = IDirectDrawSurface2_GetSurfaceDesc(src, &surface_desc);
13316 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13317 ok(!surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue
13318 && !surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue,
13319 "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
13320 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
13322 /* Try blitting without keys in the destination surface. */
13323 hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_SRCBLT, NULL);
13324 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13325 hr = IDirectDrawSurface2_SetColorKey(dst, DDCKEY_DESTBLT, NULL);
13326 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13328 /* This fails, as sanity would dictate. */
13329 hr = IDirectDrawSurface2_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13330 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13332 done:
13333 IDirectDrawSurface2_Release(src);
13334 IDirectDrawSurface2_Release(dst);
13335 refcount = IDirectDraw2_Release(ddraw);
13336 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13337 DestroyWindow(window);
13340 static void test_set_render_state(void)
13342 IDirect3DDevice2 *device;
13343 IDirectDraw2 *ddraw;
13344 ULONG refcount;
13345 HWND window;
13346 DWORD state;
13347 HRESULT hr;
13349 window = create_window();
13350 ddraw = create_ddraw();
13351 ok(!!ddraw, "Failed to create a ddraw object.\n");
13352 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
13354 skip("Failed to create 3D device.\n");
13355 DestroyWindow(window);
13356 return;
13359 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, TRUE);
13360 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13361 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, FALSE);
13362 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13364 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
13365 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13366 state = 0xdeadbeef;
13367 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, &state);
13368 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13369 ok(!state, "Got unexpected render state %#x.\n", state);
13370 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
13371 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13372 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, &state);
13373 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13374 ok(state == D3DTBLEND_MODULATE, "Got unexpected render state %#x.\n", state);
13376 refcount = IDirect3DDevice2_Release(device);
13377 ok(!refcount, "Device has %u references left.\n", refcount);
13378 refcount = IDirectDraw2_Release(ddraw);
13379 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13380 DestroyWindow(window);
13383 static void test_depth_readback(void)
13385 DWORD depth, expected_depth, max_diff, passed_fmts = 0;
13386 IDirect3DMaterial2 *blue_background;
13387 IDirectDrawSurface *rt, *ds;
13388 IDirect3DViewport2 *viewport;
13389 DDSURFACEDESC surface_desc;
13390 IDirect3DDevice2 *device;
13391 unsigned int i, x, y;
13392 IDirectDraw2 *ddraw;
13393 ULONG refcount;
13394 HWND window;
13395 HRESULT hr;
13396 void *ptr;
13397 BOOL all_pass;
13399 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
13400 static D3DLVERTEX quad[] =
13402 {{-1.0f}, {-1.0f}, {0.1f}, 0, {0xff00ff00}},
13403 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
13404 {{ 1.0f}, {-1.0f}, {1.0f}, 0, {0xff00ff00}},
13405 {{ 1.0f}, { 1.0f}, {0.9f}, 0, {0xff00ff00}},
13408 static const struct
13410 unsigned int z_depth, z_mask;
13412 tests[] =
13414 {16, 0x0000ffff},
13415 {24, 0x00ffffff},
13416 {32, 0xffffffff},
13419 window = create_window();
13420 ok(!!window, "Failed to create a window.\n");
13421 ddraw = create_ddraw();
13422 ok(!!ddraw, "Failed to create a ddraw object.\n");
13423 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
13425 skip("Failed to create a D3D device, skipping tests.\n");
13426 IDirectDraw2_Release(ddraw);
13427 DestroyWindow(window);
13428 return;
13431 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
13432 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
13433 blue_background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
13434 viewport = create_viewport(device, 0, 0, 640, 480);
13435 viewport_set_background(device, viewport, blue_background);
13436 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
13437 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
13439 ds = get_depth_stencil(device);
13440 hr = IDirectDrawSurface_DeleteAttachedSurface(rt, 0, ds);
13441 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
13442 IDirectDrawSurface_Release(ds);
13444 for (i = 0; i < ARRAY_SIZE(tests); ++i)
13446 memset(&surface_desc, 0, sizeof(surface_desc));
13447 surface_desc.dwSize = sizeof(surface_desc);
13448 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
13449 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
13450 U2(surface_desc).dwZBufferBitDepth = tests[i].z_depth;
13451 surface_desc.dwWidth = 640;
13452 surface_desc.dwHeight = 480;
13453 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
13454 if (FAILED(hr))
13456 skip("Format %u not supported, skipping test.\n", i);
13457 continue;
13460 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
13461 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
13462 hr = IDirect3DDevice2_SetRenderTarget(device, rt, 0);
13463 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
13465 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
13466 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13467 hr = IDirect3DDevice2_BeginScene(device);
13468 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13469 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
13470 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13471 hr = IDirect3DDevice2_EndScene(device);
13472 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13474 memset(&surface_desc, 0, sizeof(surface_desc));
13475 surface_desc.dwSize = sizeof(surface_desc);
13476 hr = IDirectDrawSurface_Lock(ds, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13477 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13479 all_pass = TRUE;
13480 for (y = 60; y < 480; y += 120)
13482 for (x = 80; x < 640; x += 160)
13484 ptr = (BYTE *)surface_desc.lpSurface
13485 + y * U1(surface_desc).lPitch
13486 + x * (tests[i].z_depth == 16 ? 2 : 4);
13487 depth = *((DWORD *)ptr) & tests[i].z_mask;
13488 expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
13489 max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
13490 /* The ddraw2 version of this test behaves similarly to the ddraw7 version on Nvidia GPUs,
13491 * except that we only have D16 (broken on geforce 9) and D24X8 (broken on geforce 7) available.
13492 * Accept all nvidia GPUs as broken here, but still expect one of the formats to pass. */
13493 ok(compare_uint(expected_depth, depth, max_diff) || ddraw_is_nvidia(ddraw),
13494 "Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
13495 i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
13496 if (!compare_uint(expected_depth, depth, max_diff))
13497 all_pass = FALSE;
13501 hr = IDirectDrawSurface_Unlock(ds, NULL);
13502 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13504 if (all_pass)
13505 passed_fmts++;
13507 hr = IDirectDrawSurface_DeleteAttachedSurface(rt, 0, ds);
13508 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
13509 IDirectDrawSurface_Release(ds);
13512 ok(passed_fmts, "Not a single format passed the tests, this is bad even by Nvidia's standards.\n");
13514 destroy_viewport(device, viewport);
13515 destroy_material(blue_background);
13516 IDirectDrawSurface_Release(rt);
13517 refcount = IDirect3DDevice2_Release(device);
13518 ok(!refcount, "Device has %u references left.\n", refcount);
13519 IDirectDraw2_Release(ddraw);
13520 DestroyWindow(window);
13523 static void test_clear(void)
13525 D3DRECT rect_negneg, rect_full = {{0}, {0}, {640}, {480}};
13526 IDirect3DViewport2 *viewport, *viewport2, *viewport3;
13527 IDirect3DMaterial2 *white, *red, *green, *blue;
13528 IDirect3DDevice2 *device;
13529 IDirectDrawSurface *rt;
13530 IDirectDraw2 *ddraw;
13531 D3DRECT rect[2];
13532 D3DCOLOR color;
13533 ULONG refcount;
13534 HWND window;
13535 HRESULT hr;
13537 window = create_window();
13538 ddraw = create_ddraw();
13539 ok(!!ddraw, "Failed to create a ddraw object.\n");
13540 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
13542 skip("Failed to create a 3D device, skipping test.\n");
13543 IDirectDraw2_Release(ddraw);
13544 DestroyWindow(window);
13545 return;
13547 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
13548 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
13550 viewport = create_viewport(device, 0, 0, 640, 480);
13551 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
13552 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
13554 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
13555 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
13556 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
13557 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
13559 viewport_set_background(device, viewport, white);
13560 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
13561 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13563 /* Positive x, negative y. */
13564 U1(rect[0]).x1 = 0;
13565 U2(rect[0]).y1 = 480;
13566 U3(rect[0]).x2 = 320;
13567 U4(rect[0]).y2 = 240;
13569 /* Positive x, positive y. */
13570 U1(rect[1]).x1 = 0;
13571 U2(rect[1]).y1 = 0;
13572 U3(rect[1]).x2 = 320;
13573 U4(rect[1]).y2 = 240;
13575 /* Clear 2 rectangles with one call. Unlike d3d8/9, the refrast does not
13576 * refuse negative rectangles, but it will not clear them either. */
13577 viewport_set_background(device, viewport, red);
13578 hr = IDirect3DViewport2_Clear(viewport, 2, rect, D3DCLEAR_TARGET);
13579 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13581 color = get_surface_color(rt, 160, 360);
13582 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 3 (pos, neg) has color 0x%08x.\n", color);
13583 color = get_surface_color(rt, 160, 120);
13584 ok(compare_color(color, 0x00ff0000, 0), "Clear rectangle 1 (pos, pos) has color 0x%08x.\n", color);
13585 color = get_surface_color(rt, 480, 360);
13586 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (NULL) has color 0x%08x.\n", color);
13587 color = get_surface_color(rt, 480, 120);
13588 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (neg, neg) has color 0x%08x.\n", color);
13590 viewport_set_background(device, viewport, white);
13591 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
13592 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13594 /* negative x, negative y.
13595 * Also ignored, except on WARP, which clears the entire screen. */
13596 U1(rect_negneg).x1 = 640;
13597 U2(rect_negneg).y1 = 240;
13598 U3(rect_negneg).x2 = 320;
13599 U4(rect_negneg).y2 = 0;
13600 viewport_set_background(device, viewport, green);
13601 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_negneg, D3DCLEAR_TARGET);
13602 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13604 color = get_surface_color(rt, 160, 360);
13605 ok(compare_color(color, 0x00ffffff, 0)
13606 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
13607 "Got unexpected color 0x%08x.\n", color);
13608 color = get_surface_color(rt, 160, 120);
13609 ok(compare_color(color, 0x00ffffff, 0)
13610 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
13611 "Got unexpected color 0x%08x.\n", color);
13612 color = get_surface_color(rt, 480, 360);
13613 ok(compare_color(color, 0x00ffffff, 0)
13614 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
13615 "Got unexpected color 0x%08x.\n", color);
13616 color = get_surface_color(rt, 480, 120);
13617 ok(compare_color(color, 0x00ffffff, 0)
13618 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
13619 "Got unexpected color 0x%08x.\n", color);
13621 /* Test how the viewport affects clears. */
13622 viewport_set_background(device, viewport, white);
13623 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
13624 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13626 viewport2 = create_viewport(device, 160, 120, 160, 120);
13627 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
13628 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
13630 viewport_set_background(device, viewport2, blue);
13631 hr = IDirect3DViewport2_Clear(viewport2, 1, &rect_full, D3DCLEAR_TARGET);
13632 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13634 viewport3 = create_viewport(device, 320, 240, 320, 240);
13635 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport3);
13636 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
13638 U1(rect[0]).x1 = 160;
13639 U2(rect[0]).y1 = 120;
13640 U3(rect[0]).x2 = 480;
13641 U4(rect[0]).y2 = 360;
13642 viewport_set_background(device, viewport3, green);
13643 hr = IDirect3DViewport2_Clear(viewport3, 1, &rect[0], D3DCLEAR_TARGET);
13644 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13646 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
13647 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
13649 color = get_surface_color(rt, 158, 118);
13650 ok(compare_color(color, 0x00ffffff, 0), "(158, 118) has color 0x%08x.\n", color);
13651 color = get_surface_color(rt, 162, 118);
13652 ok(compare_color(color, 0x00ffffff, 0), "(162, 118) has color 0x%08x.\n", color);
13653 color = get_surface_color(rt, 158, 122);
13654 ok(compare_color(color, 0x00ffffff, 0), "(158, 122) has color 0x%08x.\n", color);
13655 color = get_surface_color(rt, 162, 122);
13656 ok(compare_color(color, 0x000000ff, 0), "(162, 122) has color 0x%08x.\n", color);
13658 color = get_surface_color(rt, 318, 238);
13659 ok(compare_color(color, 0x000000ff, 0), "(318, 238) has color 0x%08x.\n", color);
13660 color = get_surface_color(rt, 322, 238);
13661 ok(compare_color(color, 0x00ffffff, 0), "(322, 238) has color 0x%08x.\n", color);
13662 color = get_surface_color(rt, 318, 242);
13663 ok(compare_color(color, 0x00ffffff, 0), "(318, 242) has color 0x%08x.\n", color);
13664 color = get_surface_color(rt, 322, 242);
13665 ok(compare_color(color, 0x0000ff00, 0), "(322, 242) has color 0x%08x.\n", color);
13667 color = get_surface_color(rt, 478, 358);
13668 ok(compare_color(color, 0x0000ff00, 0), "(478, 358) has color 0x%08x.\n", color);
13669 color = get_surface_color(rt, 482, 358);
13670 ok(compare_color(color, 0x00ffffff, 0), "(482, 358) has color 0x%08x.\n", color);
13671 color = get_surface_color(rt, 478, 362);
13672 ok(compare_color(color, 0x00ffffff, 0), "(478, 362) has color 0x%08x.\n", color);
13673 color = get_surface_color(rt, 482, 362);
13674 ok(compare_color(color, 0x00ffffff, 0), "(482, 362) has color 0x%08x.\n", color);
13676 /* The clear rectangle is rendertarget absolute, not relative to the
13677 * viewport. */
13678 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
13679 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13680 U1(rect[0]).x1 = 330;
13681 U2(rect[0]).y1 = 250;
13682 U3(rect[0]).x2 = 340;
13683 U4(rect[0]).y2 = 260;
13684 hr = IDirect3DViewport2_Clear(viewport3, 1, &rect[0], D3DCLEAR_TARGET);
13685 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13687 color = get_surface_color(rt, 328, 248);
13688 ok(compare_color(color, 0x00ffffff, 0), "(328, 248) has color 0x%08x.\n", color);
13689 color = get_surface_color(rt, 332, 248);
13690 ok(compare_color(color, 0x00ffffff, 0), "(332, 248) has color 0x%08x.\n", color);
13691 color = get_surface_color(rt, 328, 252);
13692 ok(compare_color(color, 0x00ffffff, 0), "(328, 252) has color 0x%08x.\n", color);
13693 color = get_surface_color(rt, 332, 252);
13694 ok(compare_color(color, 0x0000ff00, 0), "(332, 252) has color 0x%08x.\n", color);
13696 color = get_surface_color(rt, 338, 248);
13697 ok(compare_color(color, 0x00ffffff, 0), "(338, 248) has color 0x%08x.\n", color);
13698 color = get_surface_color(rt, 342, 248);
13699 ok(compare_color(color, 0x00ffffff, 0), "(342, 248) has color 0x%08x.\n", color);
13700 color = get_surface_color(rt, 338, 252);
13701 ok(compare_color(color, 0x0000ff00, 0), "(338, 252) has color 0x%08x.\n", color);
13702 color = get_surface_color(rt, 342, 252);
13703 ok(compare_color(color, 0x00ffffff, 0), "(342, 252) has color 0x%08x.\n", color);
13705 color = get_surface_color(rt, 328, 258);
13706 ok(compare_color(color, 0x00ffffff, 0), "(328, 258) has color 0x%08x.\n", color);
13707 color = get_surface_color(rt, 332, 258);
13708 ok(compare_color(color, 0x0000ff00, 0), "(332, 258) has color 0x%08x.\n", color);
13709 color = get_surface_color(rt, 328, 262);
13710 ok(compare_color(color, 0x00ffffff, 0), "(328, 262) has color 0x%08x.\n", color);
13711 color = get_surface_color(rt, 332, 262);
13712 ok(compare_color(color, 0x00ffffff, 0), "(332, 262) has color 0x%08x.\n", color);
13714 color = get_surface_color(rt, 338, 258);
13715 ok(compare_color(color, 0x0000ff00, 0), "(338, 258) has color 0x%08x.\n", color);
13716 color = get_surface_color(rt, 342, 258);
13717 ok(compare_color(color, 0x00ffffff, 0), "(342, 258) has color 0x%08x.\n", color);
13718 color = get_surface_color(rt, 338, 262);
13719 ok(compare_color(color, 0x00ffffff, 0), "(338, 262) has color 0x%08x.\n", color);
13720 color = get_surface_color(rt, 342, 262);
13721 ok(compare_color(color, 0x00ffffff, 0), "(342, 262) has color 0x%08x.\n", color);
13723 /* COLORWRITEENABLE, SRGBWRITEENABLE and scissor rectangles do not exist
13724 * in d3d2. */
13726 IDirect3DViewport2_Release(viewport3);
13727 IDirect3DViewport2_Release(viewport2);
13728 IDirect3DViewport2_Release(viewport);
13729 IDirect3DMaterial2_Release(white);
13730 IDirect3DMaterial2_Release(red);
13731 IDirect3DMaterial2_Release(green);
13732 IDirect3DMaterial2_Release(blue);
13733 IDirectDrawSurface_Release(rt);
13734 refcount = IDirect3DDevice2_Release(device);
13735 ok(!refcount, "Device has %u references left.\n", refcount);
13736 refcount = IDirectDraw2_Release(ddraw);
13737 ok(!refcount, "Ddraw object has %u references left.\n", refcount);
13738 DestroyWindow(window);
13741 struct enum_surfaces_param
13743 IDirectDraw2 *ddraw;
13744 DDSURFACEDESC modes[20];
13745 unsigned int mode_count;
13747 IDirectDrawSurface *surfaces[8];
13748 unsigned int count;
13751 static HRESULT CALLBACK build_mode_list_cb(DDSURFACEDESC *desc, void *context)
13753 struct enum_surfaces_param *param = context;
13754 IDirectDrawSurface *surface;
13756 if (SUCCEEDED(IDirectDraw2_CreateSurface(param->ddraw, desc, &surface, NULL)))
13758 if (param->mode_count < ARRAY_SIZE(param->modes))
13759 param->modes[param->mode_count] = *desc;
13760 ++param->mode_count;
13761 IDirectDrawSurface_Release(surface);
13764 return DDENUMRET_OK;
13767 static HRESULT WINAPI enum_surfaces_cb(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
13769 struct enum_surfaces_param *param = context;
13770 BOOL found = FALSE;
13771 unsigned int i;
13773 for (i = 0; i < ARRAY_SIZE(param->surfaces); ++i)
13775 if (param->surfaces[i] == surface)
13777 found = TRUE;
13778 break;
13782 ok(found, "Unexpected surface %p enumerated.\n", surface);
13783 IDirectDrawSurface_Release(surface);
13784 ++param->count;
13786 return DDENUMRET_OK;
13789 static HRESULT WINAPI enum_surfaces_create_cb(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
13791 static const DWORD expect_flags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_PIXELFORMAT;
13792 struct enum_surfaces_param *param = context;
13794 ok(!surface, "Unexpected surface %p.\n", surface);
13795 ok((desc->dwFlags & expect_flags) == expect_flags, "Got unexpected flags %#x.\n", desc->dwFlags);
13796 if (param->count < ARRAY_SIZE(param->modes))
13798 const DDSURFACEDESC *expect = &param->modes[param->count];
13799 ok(desc->dwWidth == expect->dwWidth, "Expected width %u, got %u.\n", expect->dwWidth, desc->dwWidth);
13800 ok(desc->dwHeight == expect->dwHeight, "Expected height %u, got %u.\n", expect->dwHeight, desc->dwHeight);
13801 ok(!memcmp(&U4(*desc).ddpfPixelFormat, &U4(*expect).ddpfPixelFormat, sizeof(U4(*desc).ddpfPixelFormat)),
13802 "Pixel formats didn't match.\n");
13805 ++param->count;
13807 return DDENUMRET_OK;
13810 static void test_enum_surfaces(void)
13812 struct enum_surfaces_param param = {0};
13813 DDPIXELFORMAT current_format;
13814 IDirectDraw2 *ddraw;
13815 DDSURFACEDESC desc;
13816 HRESULT hr;
13818 ddraw = create_ddraw();
13819 ok(!!ddraw, "Failed to create a ddraw object.\n");
13820 param.ddraw = ddraw;
13822 memset(&desc, 0, sizeof(desc));
13823 desc.dwSize = sizeof(desc);
13824 hr = IDirectDraw2_GetDisplayMode(ddraw, &desc);
13825 ok(hr == DD_OK, "Failed to get display mode, hr %#x.\n", hr);
13826 current_format = desc.ddpfPixelFormat;
13828 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
13829 ok(hr == DD_OK, "Failed to set cooperative level, hr %#x.\n", hr);
13831 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_ALL, NULL, NULL, enum_surfaces_cb);
13832 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13834 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_ALL,
13835 NULL, NULL, enum_surfaces_cb);
13836 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13838 memset(&desc, 0, sizeof(desc));
13839 desc.dwSize = sizeof(desc);
13840 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
13841 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
13842 U2(desc).dwMipMapCount = 3;
13843 desc.dwWidth = 32;
13844 desc.dwHeight = 32;
13845 hr = IDirectDraw2_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL);
13846 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
13848 hr = IDirectDrawSurface_GetAttachedSurface(param.surfaces[0], &desc.ddsCaps, &param.surfaces[1]);
13849 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
13850 hr = IDirectDrawSurface_GetAttachedSurface(param.surfaces[1], &desc.ddsCaps, &param.surfaces[2]);
13851 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
13852 hr = IDirectDrawSurface_GetAttachedSurface(param.surfaces[2], &desc.ddsCaps, &param.surfaces[3]);
13853 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13854 ok(!param.surfaces[3], "Got unexpected pointer %p.\n", param.surfaces[3]);
13856 param.count = 0;
13857 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
13858 &desc, &param, enum_surfaces_cb);
13859 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
13860 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13862 param.count = 0;
13863 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
13864 NULL, &param, enum_surfaces_cb);
13865 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
13866 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13868 desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
13869 param.count = 0;
13870 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
13871 &desc, &param, enum_surfaces_cb);
13872 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
13873 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13875 param.count = 0;
13876 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_NOMATCH,
13877 &desc, &param, enum_surfaces_cb);
13878 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
13879 ok(param.count == 2, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13881 desc.dwFlags = 0;
13882 param.count = 0;
13883 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
13884 &desc, &param, enum_surfaces_cb);
13885 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
13886 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13888 desc.dwFlags = 0;
13889 param.count = 0;
13890 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST, &desc, &param, enum_surfaces_cb);
13891 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
13892 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13894 IDirectDrawSurface_Release(param.surfaces[2]);
13895 IDirectDrawSurface_Release(param.surfaces[1]);
13896 IDirectDrawSurface_Release(param.surfaces[0]);
13898 param.count = 0;
13899 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
13900 NULL, &param, enum_surfaces_cb);
13901 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
13902 ok(!param.count, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13904 memset(&desc, 0, sizeof(desc));
13905 desc.dwSize = sizeof(desc);
13906 desc.dwFlags = DDSD_CAPS;
13907 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
13909 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_ALL,
13910 &desc, &param, enum_surfaces_create_cb);
13911 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#x.\n", hr);
13913 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_NOMATCH,
13914 &desc, &param, enum_surfaces_create_cb);
13915 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#x.\n", hr);
13917 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED,
13918 &desc, &param, enum_surfaces_create_cb);
13919 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#x.\n", hr);
13921 /* When not passed width and height, the callback is called with every
13922 * available display resolution. */
13924 param.mode_count = 0;
13925 desc.dwFlags |= DDSD_PIXELFORMAT;
13926 U4(desc).ddpfPixelFormat = current_format;
13927 hr = IDirectDraw2_EnumDisplayModes(ddraw, 0, &desc, &param, build_mode_list_cb);
13928 ok(hr == DD_OK, "Failed to build mode list, hr %#x.\n", hr);
13930 param.count = 0;
13931 desc.dwFlags &= ~DDSD_PIXELFORMAT;
13932 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
13933 &desc, &param, enum_surfaces_create_cb);
13934 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
13935 ok(param.count == param.mode_count, "Expected %u surfaces, got %u.\n", param.mode_count, param.count);
13937 desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
13938 desc.dwWidth = desc.dwHeight = 32;
13940 param.modes[0].dwWidth = param.modes[0].dwHeight = 32;
13942 param.count = 0;
13943 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
13944 &desc, &param, enum_surfaces_create_cb);
13945 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
13946 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13948 hr = IDirectDraw2_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL);
13949 ok(hr == DD_OK, "Failed to create surface, hr %#x.\n", hr);
13950 param.count = 0;
13951 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
13952 &desc, &param, enum_surfaces_create_cb);
13953 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
13954 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13955 IDirectDrawSurface2_Release(param.surfaces[0]);
13957 desc.dwFlags |= DDSD_PIXELFORMAT;
13958 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
13959 desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
13960 desc.ddpfPixelFormat.dwFourCC = 0xdeadbeef;
13962 param.count = 0;
13963 hr = IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
13964 &desc, &param, enum_surfaces_create_cb);
13965 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
13966 ok(!param.count, "Got unexpected number of enumerated surfaces %u.\n", param.count);
13968 IDirectDraw2_Release(ddraw);
13971 static void test_viewport(void)
13973 static struct
13975 D3DVIEWPORT7 vp;
13976 RECT expected_rect;
13977 const char *message;
13979 tests[] =
13981 {{ 0, 0, 640, 480}, { 0, 120, 479, 359}, "Viewport (0, 0) - (640, 480)"},
13982 {{ 0, 0, 320, 240}, { 0, 60, 239, 179}, "Viewport (0, 0) - (320, 240)"},
13983 {{ 0, 0, 1280, 960}, { 0, 240, 639, 479}, "Viewport (0, 0) - (1280, 960)"},
13984 {{ 0, 0, 2000, 1600}, { 0, 400, 639, 479}, "Viewport (0, 0) - (2000, 1600)"},
13985 {{100, 100, 640, 480}, {100, 220, 579, 459}, "Viewport (100, 100) - (640, 480)"},
13986 {{ 0, 0, 8192, 8192}, {-10, -10, -10, -10}, "Viewport (0, 0) - (8192, 8192)"},
13988 static const struct vec2 rt_sizes[] =
13990 {640, 480}, {1280, 960}, {320, 240}, {800, 600},
13992 static D3DMATRIX mat =
13994 1.0f, 0.0f, 0.0f, 0.0f,
13995 0.0f, 1.0f, 0.0f, 0.0f,
13996 0.0f, 0.0f, 1.0f, 0.0f,
13997 0.0f, 0.0f, 0.0f, 1.0f,
13999 static D3DLVERTEX quad[] =
14001 {{-1.5f}, {-0.5f}, {0.1f}, 0, {0xffffffff}},
14002 {{-1.5f}, { 0.5f}, {0.1f}, 0, {0xffffffff}},
14003 {{ 0.5f}, {-0.5f}, {0.1f}, 0, {0xffffffff}},
14004 {{ 0.5f}, { 0.5f}, {0.1f}, 0, {0xffffffff}},
14006 IDirect3DViewport2 *viewport, *full_viewport;
14007 IDirect3DMaterial2 *black_background;
14008 IDirectDrawSurface *rt, *ds;
14009 DDSURFACEDESC surface_desc;
14010 IDirect3DDevice2 *device;
14011 BOOL expected_failure;
14012 IDirectDraw2 *ddraw;
14013 DDPIXELFORMAT z_fmt;
14014 D3DRECT clear_rect;
14015 unsigned int i, j;
14016 IDirect3D2 *d3d;
14017 D3DVIEWPORT vp;
14018 ULONG refcount;
14019 HWND window;
14020 HRESULT hr;
14022 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
14023 0, 0, 640, 480, NULL, NULL, NULL, NULL);
14024 ddraw = create_ddraw();
14025 ok(!!ddraw, "Failed to create a ddraw object.\n");
14026 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
14028 skip("Failed to create a 3D device, skipping test.\n");
14029 IDirectDraw2_Release(ddraw);
14030 DestroyWindow(window);
14031 return;
14034 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
14035 ok(SUCCEEDED(hr), "Failed to get Direct3D2 interface, hr %#x.\n", hr);
14037 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
14038 ok(SUCCEEDED(hr), "Failed to disable depth test, hr %#x.\n", hr);
14039 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
14040 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
14042 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
14043 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
14044 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
14045 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
14046 hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
14047 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
14049 black_background = create_diffuse_material(device, 0.0f, 0.0f, 0.0f, 0.0f);
14051 ds = get_depth_stencil(device);
14052 memset(&surface_desc, 0, sizeof(surface_desc));
14053 surface_desc.dwSize = sizeof(surface_desc);
14054 hr = IDirectDrawSurface_GetSurfaceDesc(ds, &surface_desc);
14055 z_fmt = surface_desc.ddpfPixelFormat;
14057 for (i = 0; i < ARRAY_SIZE(rt_sizes); ++i)
14059 if (i)
14061 memset(&surface_desc, 0, sizeof(surface_desc));
14062 surface_desc.dwSize = sizeof(surface_desc);
14063 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
14064 surface_desc.dwWidth = rt_sizes[i].x;
14065 surface_desc.dwHeight = rt_sizes[i].y;
14066 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
14067 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &rt, NULL);
14068 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x (i %u).\n", hr, i);
14070 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
14071 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
14072 surface_desc.ddpfPixelFormat = z_fmt;
14073 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
14074 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x (i %u).\n", hr, i);
14075 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
14076 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x (i %u).\n", hr, i);
14078 hr = IDirect3DDevice2_SetRenderTarget(device, rt, 0);
14079 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x (i %u).\n", hr, i);
14081 else
14083 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
14084 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14087 full_viewport = create_viewport(device, 0, 0, rt_sizes[i].x, rt_sizes[i].y);
14088 viewport_set_background(device, full_viewport, black_background);
14090 U1(clear_rect).x1 = U2(clear_rect).y1 = 0;
14091 U3(clear_rect).x2 = rt_sizes[i].x;
14092 U4(clear_rect).y2 = rt_sizes[i].y;
14094 for (j = 0; j < ARRAY_SIZE(tests); ++j)
14096 expected_failure = tests[j].vp.dwX + tests[j].vp.dwWidth > rt_sizes[i].x
14097 || tests[j].vp.dwY + tests[j].vp.dwHeight > rt_sizes[i].y;
14099 hr = IDirect3DViewport2_Clear(full_viewport, 1, &clear_rect, D3DCLEAR_TARGET);
14100 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x (i %u, j %u).\n", hr, i, j);
14102 hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
14103 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x (i %u, j %u).\n", hr, i, j);
14104 hr = IDirect3DViewport2_SetViewport2(viewport, NULL);
14105 ok(hr == E_INVALIDARG, "Setting NULL viewport data returned unexpected hr %#x (i %u, j %u).\n",
14106 hr, i, j);
14107 memset(&vp, 0, sizeof(vp));
14108 vp.dwSize = sizeof(vp);
14109 vp.dwX = tests[j].vp.dwX;
14110 vp.dwY = tests[j].vp.dwY;
14111 vp.dwWidth = tests[j].vp.dwWidth;
14112 vp.dwHeight = tests[j].vp.dwHeight;
14113 vp.dvScaleX = tests[j].vp.dwWidth / 2.0f;
14114 vp.dvScaleY = tests[j].vp.dwHeight / 2.0f;
14115 vp.dvMinZ = 0.0f;
14116 vp.dvMaxZ = 1.0f;
14117 hr = IDirect3DViewport2_SetViewport(viewport, &vp);
14118 ok(hr == D3DERR_VIEWPORTHASNODEVICE,
14119 "Setting viewport data returned unexpected hr %#x (i %u, j %u).\n", hr, i, j);
14120 hr = IDirect3DDevice2_AddViewport(device, viewport);
14121 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x (i %u, j %u).\n", hr, i, j);
14122 hr = IDirect3DViewport2_SetViewport(viewport, &vp);
14123 if (expected_failure)
14124 ok(hr == E_INVALIDARG, "Setting viewport data returned unexpected hr %#x (i %u, j %u).\n",
14125 hr, i, j);
14126 else
14127 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x (i %u, j %u).\n", hr, i, j);
14129 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
14130 ok(SUCCEEDED(hr), "Failed to set the viewport, hr %#x (i %u, j %u).\n", hr, i, j);
14131 if (expected_failure)
14133 destroy_viewport(device, viewport);
14134 continue;
14137 hr = IDirect3DDevice2_BeginScene(device);
14138 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x (i %u, j %u).\n", hr, i, j);
14139 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
14140 ok(SUCCEEDED(hr), "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
14141 hr = IDirect3DDevice2_EndScene(device);
14142 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x (i %u, j %u).\n", hr, i, j);
14144 check_rect(rt, tests[j].expected_rect, tests[j].message);
14146 destroy_viewport(device, viewport);
14149 destroy_viewport(device, full_viewport);
14151 hr = IDirectDrawSurface_DeleteAttachedSurface(rt, 0, ds);
14152 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x (i %u).\n", hr, i);
14153 IDirectDrawSurface_Release(ds);
14155 IDirectDrawSurface_Release(rt);
14158 destroy_material(black_background);
14159 refcount = IDirect3DDevice2_Release(device);
14160 ok(!refcount, "Device has %u references left.\n", refcount);
14161 IDirect3D2_Release(d3d);
14162 IDirectDraw2_Release(ddraw);
14163 DestroyWindow(window);
14166 static void test_find_device(void)
14168 D3DFINDDEVICESEARCH search = {0};
14169 D3DFINDDEVICERESULT result = {0};
14170 IDirect3DDevice2 *device;
14171 IDirectDraw2 *ddraw;
14172 IDirect3D2 *d3d;
14173 unsigned int i;
14174 HWND window;
14175 HRESULT hr;
14177 struct
14179 DWORD size;
14180 GUID guid;
14181 D3DDEVICEDESC_V1 hw_desc;
14182 D3DDEVICEDESC_V1 sw_desc;
14183 } result_v1;
14185 struct
14187 DWORD size;
14188 GUID guid;
14189 D3DDEVICEDESC_V2 hw_desc;
14190 D3DDEVICEDESC_V2 sw_desc;
14191 } result_v2;
14193 static const struct
14195 const GUID *guid;
14196 HRESULT hr;
14198 tests[] =
14200 {&IID_IDirect3D, DDERR_NOTFOUND},
14201 {&IID_IDirect3DRampDevice, D3D_OK},
14202 {&IID_IDirect3DRGBDevice, D3D_OK},
14203 {&IID_IDirect3DMMXDevice, D3D_OK},
14204 {&IID_IDirect3DRefDevice, DDERR_NOTFOUND},
14205 {&IID_IDirect3DTnLHalDevice, DDERR_NOTFOUND},
14206 {&IID_IDirect3DNullDevice, DDERR_NOTFOUND},
14209 ddraw = create_ddraw();
14210 ok(!!ddraw, "Failed to create a ddraw object.\n");
14212 if (FAILED(IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
14214 skip("D3D interface is not available, skipping test.\n");
14215 IDirectDraw2_Release(ddraw);
14216 return;
14219 result.dwSize = sizeof(result);
14220 search.dwSize = sizeof(search);
14221 hr = IDirect3D2_FindDevice(d3d, NULL, NULL);
14222 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14223 hr = IDirect3D2_FindDevice(d3d, NULL, &result);
14224 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14225 hr = IDirect3D2_FindDevice(d3d, &search, NULL);
14226 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14227 hr = IDirect3D2_FindDevice(d3d, &search, &result);
14228 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14229 ok(result.dwSize == sizeof(result), "Got unexpected result size %u.\n", result.dwSize);
14230 ok(result.ddHwDesc.dwSize == sizeof(result_v2.hw_desc),
14231 "Got unexpected HW desc size %u.\n", result.ddHwDesc.dwSize);
14232 ok(result.ddSwDesc.dwSize == sizeof(result_v2.sw_desc),
14233 "Got unexpected SW desc size %u.\n", result.ddSwDesc.dwSize);
14235 memset(&search, 0, sizeof(search));
14236 memset(&result, 0, sizeof(result));
14237 hr = IDirect3D2_FindDevice(d3d, &search, &result);
14238 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14240 search.dwSize = sizeof(search) + 1;
14241 result.dwSize = sizeof(result) + 1;
14242 hr = IDirect3D2_FindDevice(d3d, &search, &result);
14243 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14245 search.dwSize = sizeof(search);
14247 memset(&result_v1, 0, sizeof(result_v1));
14248 result_v1.size = sizeof(result_v1);
14249 hr = IDirect3D2_FindDevice(d3d, &search, (D3DFINDDEVICERESULT *)&result_v1);
14250 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14251 ok(result_v1.hw_desc.dwSize == sizeof(result_v2.hw_desc),
14252 "Got unexpected HW desc size %u.\n", result_v1.hw_desc.dwSize);
14253 ok(result_v1.sw_desc.dwSize == sizeof(result_v2.sw_desc),
14254 "Got unexpected SW desc size %u.\n", result_v1.sw_desc.dwSize);
14256 memset(&result_v2, 0, sizeof(result_v2));
14257 result_v2.size = sizeof(result_v2);
14258 hr = IDirect3D2_FindDevice(d3d, &search, (D3DFINDDEVICERESULT *)&result_v2);
14259 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14260 ok(result_v2.hw_desc.dwSize == sizeof(result_v2.hw_desc),
14261 "Got unexpected HW desc size %u.\n", result_v2.hw_desc.dwSize);
14262 ok(result_v2.sw_desc.dwSize == sizeof(result_v2.sw_desc),
14263 "Got unexpected SW desc size %u.\n", result_v2.sw_desc.dwSize);
14265 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14267 memset(&search, 0, sizeof(search));
14268 search.dwSize = sizeof(search);
14269 search.dwFlags = D3DFDS_GUID;
14270 search.guid = *tests[i].guid;
14272 memset(&result, 0, sizeof(result));
14273 result.dwSize = sizeof(result);
14275 hr = IDirect3D2_FindDevice(d3d, &search, &result);
14276 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
14277 ok(result.dwSize == sizeof(result), "Test %u: Got unexpected result size %u.\n", i, result.dwSize);
14278 if (SUCCEEDED(hr))
14280 ok(result.ddHwDesc.dwSize == sizeof(result_v2.hw_desc),
14281 "Test %u: Got unexpected HW desc size %u.\n", i, result.ddHwDesc.dwSize);
14282 ok(result.ddSwDesc.dwSize == sizeof(result_v2.sw_desc),
14283 "Test %u: Got unexpected SW desc size %u.\n", i, result.ddSwDesc.dwSize);
14285 else
14287 ok(!result.ddHwDesc.dwSize,
14288 "Test %u: Got unexpected HW desc size %u.\n", i, result.ddHwDesc.dwSize);
14289 ok(!result.ddSwDesc.dwSize,
14290 "Test %u: Got unexpected SW desc size %u.\n", i, result.ddSwDesc.dwSize);
14294 /* The HAL device can only be enumerated if hardware acceleration is present. */
14295 search.dwSize = sizeof(search);
14296 search.dwFlags = D3DFDS_GUID;
14297 search.guid = IID_IDirect3DHALDevice;
14298 result.dwSize = sizeof(result);
14299 hr = IDirect3D2_FindDevice(d3d, &search, &result);
14301 window = create_window();
14302 device = create_device(ddraw, window, DDSCL_NORMAL);
14303 if (hr == D3D_OK)
14304 ok(!!device, "Failed to create a 3D device.\n");
14305 else
14306 ok(!device, "Succeeded to create a 3D device.\n");
14307 if (device)
14308 IDirect3DDevice2_Release(device);
14309 DestroyWindow(window);
14311 /* Curiously the colour model criteria seem to be ignored. */
14312 search.dwSize = sizeof(search);
14313 search.dwFlags = D3DFDS_COLORMODEL;
14314 search.dcmColorModel = 0xdeadbeef;
14315 result.dwSize = sizeof(result);
14316 hr = IDirect3D2_FindDevice(d3d, &search, &result);
14317 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14319 IDirect3D2_Release(d3d);
14320 IDirectDraw2_Release(ddraw);
14323 static IDirectDraw2 *killfocus_ddraw;
14324 static IDirectDrawSurface *killfocus_surface;
14326 static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
14328 ULONG ref;
14330 if (message == WM_KILLFOCUS)
14332 ref = IDirectDrawSurface_Release(killfocus_surface);
14333 ok(!ref, "Unexpected surface refcount %u.\n", ref);
14334 ref = IDirectDraw2_Release(killfocus_ddraw);
14335 ok(!ref, "Unexpected ddraw refcount %u.\n", ref);
14336 killfocus_ddraw = NULL;
14339 return DefWindowProcA(window, message, wparam, lparam);
14342 static void test_killfocus(void)
14344 DDSURFACEDESC surface_desc;
14345 HRESULT hr;
14346 HWND window;
14347 WNDCLASSA wc = {0};
14349 wc.lpfnWndProc = killfocus_proc;
14350 wc.lpszClassName = "ddraw_killfocus_wndproc_wc";
14351 ok(RegisterClassA(&wc), "Failed to register window class.\n");
14353 window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
14354 0, 0, 640, 480, 0, 0, 0, 0);
14356 killfocus_ddraw = create_ddraw();
14357 ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n");
14359 hr = IDirectDraw2_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
14360 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
14362 memset(&surface_desc, 0, sizeof(surface_desc));
14363 surface_desc.dwSize = sizeof(surface_desc);
14364 surface_desc.dwFlags = DDSD_CAPS;
14365 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
14366 hr = IDirectDraw2_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL);
14367 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
14369 SetForegroundWindow(GetDesktopWindow());
14370 ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n");
14372 DestroyWindow(window);
14373 UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
14376 static void test_gdi_surface(void)
14378 IDirectDrawSurface *primary, *backbuffer, *gdi_surface;
14379 DDSCAPS caps = {DDSCAPS_BACKBUFFER};
14380 DDSURFACEDESC surface_desc;
14381 IDirectDraw2 *ddraw;
14382 ULONG refcount;
14383 HWND window;
14384 HRESULT hr;
14386 window = create_window();
14387 ddraw = create_ddraw();
14388 ok(!!ddraw, "Failed to create a ddraw object.\n");
14389 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
14390 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14392 /* Retrieving the GDI surface requires a primary surface to exist. */
14393 gdi_surface = (void *)0xc0dec0de;
14394 hr = IDirectDraw2_GetGDISurface(ddraw, &gdi_surface);
14395 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14396 ok(!gdi_surface, "Got unexpected surface %p.\n", gdi_surface);
14398 hr = IDirectDraw2_FlipToGDISurface(ddraw);
14399 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14401 memset(&surface_desc, 0, sizeof(surface_desc));
14402 surface_desc.dwSize = sizeof(surface_desc);
14403 surface_desc.dwFlags = DDSD_CAPS;
14404 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
14405 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
14406 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14408 hr = IDirectDraw2_GetGDISurface(ddraw, &gdi_surface);
14409 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14410 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
14411 IDirectDrawSurface_Release(gdi_surface);
14413 /* Flipping to the GDI surface requires the primary surface to be
14414 * flippable. */
14415 hr = IDirectDraw2_FlipToGDISurface(ddraw);
14416 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
14418 IDirectDrawSurface_Release(primary);
14420 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
14421 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14423 memset(&surface_desc, 0, sizeof(surface_desc));
14424 surface_desc.dwSize = sizeof(surface_desc);
14425 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
14426 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
14427 U5(surface_desc).dwBackBufferCount = 1;
14428 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
14429 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14430 hr = IDirectDrawSurface_GetAttachedSurface(primary, &caps, &backbuffer);
14431 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14432 ok(backbuffer != primary, "Got unexpected backbuffer %p.\n", backbuffer);
14434 hr = IDirectDraw2_GetGDISurface(ddraw, &gdi_surface);
14435 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14436 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
14437 IDirectDrawSurface_Release(gdi_surface);
14439 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
14440 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14441 hr = IDirectDraw2_GetGDISurface(ddraw, &gdi_surface);
14442 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14443 ok(gdi_surface == backbuffer || broken(gdi_surface == primary),
14444 "Got unexpected surface %p, expected %p.\n", gdi_surface, backbuffer);
14445 IDirectDrawSurface_Release(gdi_surface);
14447 hr = IDirectDraw2_FlipToGDISurface(ddraw);
14448 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14450 hr = IDirectDraw2_GetGDISurface(ddraw, &gdi_surface);
14451 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14452 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
14453 IDirectDrawSurface_Release(gdi_surface);
14455 hr = IDirectDraw2_FlipToGDISurface(ddraw);
14456 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14458 IDirectDrawSurface_Release(backbuffer);
14459 IDirectDrawSurface_Release(primary);
14461 refcount = IDirectDraw2_Release(ddraw);
14462 ok(!refcount, "%u references left.\n", refcount);
14463 DestroyWindow(window);
14466 static void test_alphatest(void)
14468 #define ALPHATEST_PASSED 0x0000ff00
14469 #define ALPHATEST_FAILED 0x00ff0000
14470 D3DRECT rect_full = {{0}, {0}, {640}, {480}};
14471 IDirect3DMaterial2 *blue, *failed;
14472 IDirect3DViewport2 *viewport;
14473 IDirect3DDevice2 *device;
14474 IDirectDrawSurface *rt;
14475 IDirectDraw2 *ddraw;
14476 unsigned int i;
14477 D3DCOLOR color;
14478 ULONG refcount;
14479 HWND window;
14480 DWORD value;
14481 HRESULT hr;
14483 static const struct
14485 D3DCMPFUNC func;
14486 D3DCOLOR color_less;
14487 D3DCOLOR color_equal;
14488 D3DCOLOR color_greater;
14490 test_data[] =
14492 {D3DCMP_NEVER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED},
14493 {D3DCMP_LESS, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED},
14494 {D3DCMP_EQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED},
14495 {D3DCMP_LESSEQUAL, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_FAILED},
14496 {D3DCMP_GREATER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_PASSED},
14497 {D3DCMP_NOTEQUAL, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED},
14498 {D3DCMP_GREATEREQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED},
14499 {D3DCMP_ALWAYS, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
14501 static D3DLVERTEX quad[] =
14503 {{-1.0f}, {-1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
14504 {{-1.0f}, { 1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
14505 {{ 1.0f}, {-1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
14506 {{ 1.0f}, { 1.0f}, {0.1f}, 0, {ALPHATEST_PASSED | 0x80000000}},
14509 window = create_window();
14510 ddraw = create_ddraw();
14511 ok(!!ddraw, "Failed to create a ddraw object.\n");
14512 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
14514 skip("Failed to create a 3D device.\n");
14515 IDirectDraw2_Release(ddraw);
14516 DestroyWindow(window);
14517 return;
14519 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
14520 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14522 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
14523 failed = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
14525 viewport = create_viewport(device, 0, 0, 640, 480);
14526 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
14527 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14529 viewport_set_background(device, viewport, blue);
14530 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
14531 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14532 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
14533 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14534 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
14535 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14536 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
14537 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14539 viewport_set_background(device, viewport, failed);
14540 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
14542 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHAFUNC, test_data[i].func);
14543 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14545 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
14546 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14547 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0x70);
14548 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14549 hr = IDirect3DDevice2_BeginScene(device);
14550 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14551 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
14552 D3DVT_LVERTEX, quad, ARRAY_SIZE(quad), 0);
14553 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14554 hr = IDirect3DDevice2_EndScene(device);
14555 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14556 color = get_surface_color(rt, 320, 240);
14557 ok(compare_color(color, test_data[i].color_greater, 0),
14558 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
14559 color, test_data[i].color_greater, test_data[i].func);
14561 hr = IDirect3DViewport2_Clear(viewport, 1, &rect_full, D3DCLEAR_TARGET);
14562 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14563 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0xff70);
14564 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14565 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHAREF, &value);
14566 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14567 ok(value == 0xff70, "Got unexpected value %#x.\n", value);
14568 hr = IDirect3DDevice2_BeginScene(device);
14569 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14570 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
14571 D3DVT_LVERTEX, quad, ARRAY_SIZE(quad), 0);
14572 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14573 hr = IDirect3DDevice2_EndScene(device);
14574 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14575 color = get_surface_color(rt, 320, 240);
14576 ok(compare_color(color, test_data[i].color_greater, 0),
14577 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
14578 color, test_data[i].color_greater, test_data[i].func);
14581 destroy_viewport(device, viewport);
14582 destroy_material(failed);
14583 destroy_material(blue);
14584 IDirectDrawSurface_Release(rt);
14585 refcount = IDirect3DDevice2_Release(device);
14586 ok(!refcount, "Device has %u references left.\n", refcount);
14587 refcount = IDirectDraw2_Release(ddraw);
14588 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
14589 DestroyWindow(window);
14592 static void test_clipper_refcount(void)
14594 IDirectDrawSurface *surface;
14595 IDirectDrawClipper *clipper, *clipper2;
14596 DDSURFACEDESC surface_desc;
14597 IDirectDraw2 *ddraw;
14598 IDirectDraw *ddraw1;
14599 ULONG refcount;
14600 HWND window;
14601 HRESULT hr;
14602 BOOL changed;
14603 const IDirectDrawClipperVtbl *orig_vtbl;
14605 window = create_window();
14606 ddraw = create_ddraw();
14607 ok(!!ddraw, "Failed to create a ddraw object.\n");
14608 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
14609 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14611 memset(&surface_desc, 0, sizeof(surface_desc));
14612 surface_desc.dwSize = sizeof(surface_desc);
14613 surface_desc.dwFlags = DDSD_CAPS;
14614 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
14615 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14616 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14618 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
14619 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
14620 refcount = get_refcount((IUnknown *)clipper);
14621 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
14623 /* Show that clipper validation doesn't somehow happen through per-clipper vtable
14624 * pointers. */
14625 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper2, NULL);
14626 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
14627 ok(clipper->lpVtbl == clipper2->lpVtbl, "Got different clipper vtables %p and %p.\n",
14628 clipper->lpVtbl, clipper2->lpVtbl);
14629 orig_vtbl = clipper->lpVtbl;
14630 IDirectDrawClipper_Release(clipper2);
14632 /* Surfaces hold a reference to clippers. No surprises there. */
14633 hr = IDirectDrawSurface_SetClipper(surface, clipper);
14634 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
14635 refcount = get_refcount((IUnknown *)clipper);
14636 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
14638 hr = IDirectDrawSurface_GetClipper(surface, &clipper2);
14639 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
14640 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
14641 refcount = IDirectDrawClipper_Release(clipper2);
14642 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
14644 hr = IDirectDrawSurface_SetClipper(surface, NULL);
14645 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
14646 refcount = get_refcount((IUnknown *)clipper);
14647 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
14649 hr = IDirectDrawSurface_SetClipper(surface, clipper);
14650 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
14651 refcount = get_refcount((IUnknown *)clipper);
14652 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
14654 refcount = IDirectDrawSurface_Release(surface);
14655 ok(!refcount, "%u references left.\n", refcount);
14656 refcount = get_refcount((IUnknown *)clipper);
14657 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
14659 /* SetClipper with an invalid pointer crashes. */
14661 /* Clipper methods work with a broken vtable, with the exception of Release. */
14662 clipper->lpVtbl = (void *)0xdeadbeef;
14663 refcount = orig_vtbl->AddRef(clipper);
14664 todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
14665 refcount = orig_vtbl->Release(clipper);
14666 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
14668 clipper->lpVtbl = orig_vtbl;
14669 refcount = orig_vtbl->Release(clipper);
14670 todo_wine ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
14672 /* Fix the refcount difference because Wine did not increase the ref in the
14673 * AddRef call above. */
14674 if (refcount)
14676 refcount = IDirectDrawClipper_Release(clipper);
14677 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
14680 /* Steal the reference and see what happens - releasing the surface works fine.
14681 * The clipper is destroyed and not kept alive by a hidden refcount - trying to
14682 * release it after the GetClipper call is likely to crash, and certain to crash
14683 * if we allocate and zero as much heap memory as we can get. */
14684 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14685 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14686 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
14687 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
14688 hr = IDirectDrawSurface_SetClipper(surface, clipper);
14689 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
14691 IDirectDrawClipper_Release(clipper);
14692 IDirectDrawClipper_Release(clipper);
14694 if (0)
14696 /* Disabled because it causes heap corruption (HeapValidate fails and random
14697 * hangs in a later HeapFree) on Windows on one of my Machines: MacbookPro 10,1
14698 * running Windows 10 18363.535 and Nvidia driver 425.31. Driver version 441.66
14699 * is affected too. Some testbot machines have crashes directly in GetClipper
14700 * or proceed with a corrupted heap too.
14702 * The same Windows and driver versions run the test without heap corruption on
14703 * a Geforce 1060 GTX card. I have not seen the problem on AMD GPUs either. */
14704 hr = IDirectDrawSurface_GetClipper(surface, &clipper2);
14705 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
14706 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
14709 /* Show that invoking the Release method does not crash, but don't get the
14710 * vtable through the clipper pointer because it is no longer pointing to
14711 * valid memory. */
14712 refcount = orig_vtbl->Release(clipper);
14713 ok(!refcount, "%u references left.\n", refcount);
14715 refcount = IDirectDrawSurface_Release(surface);
14716 ok(!refcount, "%u references left.\n", refcount);
14718 /* It looks like the protection against invalid thispointers is part of
14719 * the IDirectDrawClipper method implementation, not IDirectDrawSurface. */
14720 clipper = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x1000);
14721 ok(!!clipper, "failed to allocate memory\n");
14723 /* Assigning the vtable to our fake clipper does NOT make a difference on
14724 * native - there is a different member of the clipper implementation struct
14725 * that is used to determine if a clipper is valid. */
14726 clipper->lpVtbl = orig_vtbl;
14728 refcount = orig_vtbl->AddRef(clipper);
14729 todo_wine ok(!refcount, "Got refcount %u.\n", refcount);
14730 refcount = orig_vtbl->AddRef((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef);
14731 ok(!refcount, "Got refcount %u.\n", refcount);
14733 changed = 0x1234;
14734 hr = orig_vtbl->IsClipListChanged(clipper, &changed);
14735 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14736 todo_wine ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
14738 changed = 0x1234;
14739 hr = orig_vtbl->IsClipListChanged((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef, &changed);
14740 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14741 ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
14743 /* Nope, we can't initialize our fake clipper. */
14744 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirectDraw, (void **)&ddraw1);
14745 ok(SUCCEEDED(hr), "Failed to get ddraw1 interface, hr %#x.\n", hr);
14747 hr = orig_vtbl->Initialize(clipper, ddraw1, 0);
14748 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14750 IDirectDraw_Release(ddraw1);
14752 HeapFree(GetProcessHeap(), 0, clipper);
14754 refcount = IDirectDraw2_Release(ddraw);
14755 ok(!refcount, "%u references left.\n", refcount);
14756 DestroyWindow(window);
14759 static void test_caps(void)
14761 DWORD caps_never, caps_always, caps_hal;
14762 DDCAPS hal_caps, hel_caps;
14763 IDirectDraw2 *ddraw;
14764 IDirectDraw *ddraw1;
14765 HRESULT hr;
14766 BOOL no3d;
14768 caps_never = DDSCAPS_RESERVED1
14769 | DDSCAPS_ALPHA
14770 | DDSCAPS_PRIMARYSURFACELEFT
14771 | DDSCAPS_SYSTEMMEMORY
14772 | DDSCAPS_VISIBLE
14773 | DDSCAPS_WRITEONLY
14774 | DDSCAPS_LIVEVIDEO
14775 | DDSCAPS_HWCODEC
14776 | DDSCAPS_MODEX
14777 | DDSCAPS_RESERVED2
14778 | 0x01000000u
14779 | 0x02000000u
14780 | DDSCAPS_ALLOCONLOAD
14781 | DDSCAPS_VIDEOPORT
14782 | DDSCAPS_STANDARDVGAMODE
14783 | DDSCAPS_OPTIMIZED;
14785 caps_always = DDSCAPS_FLIP
14786 | DDSCAPS_OFFSCREENPLAIN
14787 | DDSCAPS_PRIMARYSURFACE
14788 | DDSCAPS_TEXTURE
14789 | DDSCAPS_ZBUFFER
14790 | DDSCAPS_MIPMAP;
14792 caps_hal = DDSCAPS_BACKBUFFER
14793 | DDSCAPS_COMPLEX
14794 | DDSCAPS_FRONTBUFFER
14795 | DDSCAPS_3DDEVICE
14796 | DDSCAPS_VIDEOMEMORY
14797 | DDSCAPS_LOCALVIDMEM
14798 | DDSCAPS_NONLOCALVIDMEM;
14800 ddraw = create_ddraw();
14801 ok(!!ddraw, "Failed to create a ddraw object.\n");
14803 memset(&hal_caps, 0, sizeof(hal_caps));
14804 memset(&hel_caps, 0, sizeof(hel_caps));
14805 hal_caps.dwSize = sizeof(hal_caps);
14806 hel_caps.dwSize = sizeof(hel_caps);
14807 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, &hel_caps);
14808 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14809 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
14810 "Got unexpected caps %#x, expected %#x.\n",
14811 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
14812 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
14813 "Got unexpected caps %#x, expected %#x.\n",
14814 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
14816 no3d = !(hal_caps.ddsCaps.dwCaps & DDSCAPS_3DDEVICE);
14817 if (hal_caps.ddsCaps.dwCaps)
14819 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
14820 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
14821 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
14822 "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
14824 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
14825 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
14826 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
14827 "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
14829 IDirectDraw2_Release(ddraw);
14831 if (hal_caps.ddsCaps.dwCaps)
14833 hr = DirectDrawCreate((GUID *)DDCREATE_HARDWAREONLY, &ddraw1, NULL);
14834 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14835 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw);
14836 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14837 IDirectDraw_Release(ddraw1);
14839 memset(&hal_caps, 0, sizeof(hal_caps));
14840 memset(&hel_caps, 0, sizeof(hel_caps));
14841 hal_caps.dwSize = sizeof(hal_caps);
14842 hel_caps.dwSize = sizeof(hel_caps);
14843 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, &hel_caps);
14844 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14845 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
14846 "Got unexpected caps %#x, expected %#x.\n",
14847 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
14848 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
14849 "Got unexpected caps %#x, expected %#x.\n",
14850 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
14852 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
14853 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
14854 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
14855 "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
14856 if (is_ddraw64)
14858 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
14859 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
14860 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
14861 "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
14863 else
14865 todo_wine ok(!hel_caps.ddsCaps.dwCaps, "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
14868 IDirectDraw2_Release(ddraw);
14871 hr = DirectDrawCreate((GUID *)DDCREATE_EMULATIONONLY, &ddraw1, NULL);
14872 ok(hr == DD_OK || (is_ddraw64 && hr == E_FAIL), "Got unexpected hr %#x.\n", hr);
14873 if (SUCCEEDED(hr))
14875 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw);
14876 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14877 IDirectDraw_Release(ddraw1);
14879 memset(&hal_caps, 0, sizeof(hal_caps));
14880 memset(&hel_caps, 0, sizeof(hel_caps));
14881 hal_caps.dwSize = sizeof(hal_caps);
14882 hel_caps.dwSize = sizeof(hel_caps);
14883 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, &hel_caps);
14884 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14885 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
14886 "Got unexpected caps %#x, expected %#x.\n",
14887 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
14888 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
14889 "Got unexpected caps %#x, expected %#x.\n",
14890 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
14892 todo_wine ok(!hal_caps.ddsCaps.dwCaps, "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
14893 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
14894 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
14895 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
14896 "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
14898 IDirectDraw2_Release(ddraw);
14902 static void test_d32_support(void)
14904 IDirectDrawSurface *surface;
14905 DDSURFACEDESC surface_desc;
14906 IDirectDraw2 *ddraw;
14907 ULONG refcount;
14908 HWND window;
14909 HRESULT hr;
14911 window = create_window();
14912 ddraw = create_ddraw();
14913 ok(!!ddraw, "Failed to create a ddraw object.\n");
14914 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
14915 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14917 memset(&surface_desc, 0, sizeof(surface_desc));
14918 surface_desc.dwSize = sizeof(surface_desc);
14919 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
14920 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
14921 U2(surface_desc).dwZBufferBitDepth = 32;
14922 surface_desc.dwWidth = 64;
14923 surface_desc.dwHeight = 64;
14924 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14925 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14927 memset(&surface_desc, 0, sizeof(surface_desc));
14928 surface_desc.dwSize = sizeof(surface_desc);
14929 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
14930 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14931 ok((surface_desc.dwFlags & DDSD_ZBUFFERBITDEPTH), "Got unexpected flags %#x.\n", surface_desc.dwFlags);
14932 ok(U2(surface_desc).dwZBufferBitDepth == 32,
14933 "Got unexpected dwZBufferBitDepth %u.\n", U2(surface_desc).dwZBufferBitDepth);
14934 ok(!(surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY),
14935 "Got unexpected surface caps %#x.\n", surface_desc.ddsCaps.dwCaps);
14936 IDirectDrawSurface_Release(surface);
14938 refcount = IDirectDraw2_Release(ddraw);
14939 ok(!refcount, "%u references left.\n", refcount);
14940 DestroyWindow(window);
14943 struct find_different_mode_param
14945 unsigned int old_width;
14946 unsigned int old_height;
14947 unsigned int old_frequency;
14948 unsigned int new_width;
14949 unsigned int new_height;
14950 unsigned int new_frequency;
14951 unsigned int new_bpp;
14954 static HRESULT CALLBACK find_different_mode_callback(DDSURFACEDESC *surface_desc, void *context)
14956 struct find_different_mode_param *param = context;
14958 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
14959 return DDENUMRET_OK;
14961 if (surface_desc->dwWidth != param->old_width && surface_desc->dwHeight != param->old_height &&
14962 surface_desc->dwRefreshRate != param->old_frequency)
14964 param->new_width = surface_desc->dwWidth;
14965 param->new_height = surface_desc->dwHeight;
14966 param->new_frequency = surface_desc->dwRefreshRate;
14967 param->new_bpp = surface_desc->ddpfPixelFormat.dwRGBBitCount;
14968 return DDENUMRET_CANCEL;
14971 return DDENUMRET_OK;
14974 static void test_cursor_clipping(void)
14976 struct find_different_mode_param param;
14977 DDSURFACEDESC surface_desc;
14978 RECT rect, clip_rect;
14979 IDirectDraw2 *ddraw;
14980 HWND window;
14981 HRESULT hr;
14982 BOOL ret;
14984 window = create_window();
14985 ok(!!window, "Failed to create a window.\n");
14986 ddraw = create_ddraw();
14987 ok(!!ddraw, "Failed to create a ddraw object.\n");
14989 memset(&surface_desc, 0, sizeof(surface_desc));
14990 surface_desc.dwSize = sizeof(surface_desc);
14991 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
14992 ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr);
14994 memset(&param, 0, sizeof(param));
14995 param.old_width = surface_desc.dwWidth;
14996 param.old_height = surface_desc.dwHeight;
14997 hr = IDirectDraw2_EnumDisplayModes(ddraw, 0, NULL, &param, find_different_mode_callback);
14998 ok(hr == DD_OK, "EnumDisplayModes failed, hr %#x.\n", hr);
14999 if (!(param.new_width && param.new_height))
15001 skip("Failed to find a different mode than %ux%u.\n", param.old_width, param.old_height);
15002 goto done;
15005 ret = ClipCursor(NULL);
15006 ok(ret, "ClipCursor failed, error %#x.\n", GetLastError());
15007 get_virtual_rect(&rect);
15008 ret = GetClipCursor(&clip_rect);
15009 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
15010 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15011 wine_dbgstr_rect(&clip_rect));
15013 /* Set cooperative level to normal */
15014 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
15015 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
15016 flush_events();
15017 get_virtual_rect(&rect);
15018 ret = GetClipCursor(&clip_rect);
15019 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
15020 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15021 wine_dbgstr_rect(&clip_rect));
15023 hr = set_display_mode(ddraw, param.new_width, param.new_height);
15024 ok(hr == DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode failed, hr %#x.\n", hr);
15025 if (FAILED(hr))
15027 win_skip("SetDisplayMode failed, hr %#x.\n", hr);
15028 goto done;
15030 flush_events();
15031 get_virtual_rect(&rect);
15032 ret = GetClipCursor(&clip_rect);
15033 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
15034 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15035 wine_dbgstr_rect(&clip_rect));
15037 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
15038 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
15039 flush_events();
15040 get_virtual_rect(&rect);
15041 ret = GetClipCursor(&clip_rect);
15042 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
15043 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15044 wine_dbgstr_rect(&clip_rect));
15046 /* Switch to full screen cooperative level */
15047 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
15048 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
15049 flush_events();
15050 SetRect(&rect, 0, 0, param.old_width, param.old_height);
15051 ret = GetClipCursor(&clip_rect);
15052 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
15053 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15054 wine_dbgstr_rect(&clip_rect));
15056 hr = set_display_mode(ddraw, param.new_width, param.new_height);
15057 ok(hr == DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode failed, hr %#x.\n", hr);
15058 if (FAILED(hr))
15060 win_skip("SetDisplayMode failed, hr %#x.\n", hr);
15061 goto done;
15063 flush_events();
15064 SetRect(&rect, 0, 0, param.new_width, param.new_height);
15065 ret = GetClipCursor(&clip_rect);
15066 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
15067 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15068 wine_dbgstr_rect(&clip_rect));
15070 /* Restore display mode */
15071 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
15072 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
15073 flush_events();
15074 SetRect(&rect, 0, 0, param.old_width, param.old_height);
15075 ret = GetClipCursor(&clip_rect);
15076 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
15077 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15078 wine_dbgstr_rect(&clip_rect));
15080 /* Switch to normal cooperative level */
15081 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
15082 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
15083 flush_events();
15084 get_virtual_rect(&rect);
15085 ret = GetClipCursor(&clip_rect);
15086 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
15087 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
15088 wine_dbgstr_rect(&clip_rect));
15090 done:
15091 IDirectDraw2_Release(ddraw);
15092 DestroyWindow(window);
15095 static BOOL CALLBACK test_window_position_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect,
15096 LPARAM lparam)
15098 RECT primary_rect, window_rect;
15099 IDirectDraw2 *ddraw;
15100 HWND window;
15101 HRESULT hr;
15102 BOOL ret;
15104 ddraw = create_ddraw();
15105 ok(!!ddraw, "Failed to create a ddraw object.\n");
15106 window = CreateWindowA("static", "ddraw_test", WS_POPUP | WS_VISIBLE, monitor_rect->left,
15107 monitor_rect->top, monitor_rect->right - monitor_rect->left,
15108 monitor_rect->bottom - monitor_rect->top, NULL, NULL, NULL, NULL);
15109 ok(!!window, "Failed to create a window.\n");
15110 flush_events();
15112 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
15113 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
15114 flush_events();
15115 ret = GetWindowRect(window, &window_rect);
15116 ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError());
15117 SetRect(&primary_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
15118 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
15119 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
15121 /* Window activation should restore the window to fit the whole primary monitor */
15122 ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0,
15123 SWP_NOZORDER | SWP_NOSIZE);
15124 ok(ret, "SetWindowPos failed, error %#x.\n", GetLastError());
15125 ret = SetForegroundWindow(GetDesktopWindow());
15126 ok(ret, "Failed to set foreground window.\n");
15127 flush_events();
15128 ret = ShowWindow(window, SW_RESTORE);
15129 ok(ret, "Failed to restore window, error %#x.\n", GetLastError());
15130 flush_events();
15131 ret = SetForegroundWindow(window);
15132 ok(ret, "SetForegroundWindow failed, error %#x.\n", GetLastError());
15133 flush_events();
15134 ret = GetWindowRect(window, &window_rect);
15135 ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError());
15136 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
15137 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
15139 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
15140 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
15141 ret = GetWindowRect(window, &window_rect);
15142 ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError());
15143 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
15144 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
15146 DestroyWindow(window);
15147 IDirectDraw2_Release(ddraw);
15148 return TRUE;
15151 static void test_window_position(void)
15153 EnumDisplayMonitors(NULL, NULL, test_window_position_cb, 0);
15156 static BOOL CALLBACK test_get_display_mode_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect,
15157 LPARAM lparam)
15159 DDSURFACEDESC surface_desc;
15160 IDirectDraw2 *ddraw;
15161 HWND window;
15162 HRESULT hr;
15163 BOOL ret;
15165 ddraw = create_ddraw();
15166 ok(!!ddraw, "Failed to create a ddraw object.\n");
15167 window = create_window();
15168 ok(!!window, "Failed to create a window.\n");
15170 /* Test that DirectDraw doesn't use the device window to determine which monitor to use */
15171 ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0,
15172 SWP_NOZORDER | SWP_NOSIZE);
15173 ok(ret, "SetWindowPos failed, error %#x.\n", GetLastError());
15175 surface_desc.dwSize = sizeof(surface_desc);
15176 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
15177 ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr);
15178 ok(surface_desc.dwWidth == GetSystemMetrics(SM_CXSCREEN), "Expect width %d, got %d.\n",
15179 GetSystemMetrics(SM_CXSCREEN), surface_desc.dwWidth);
15180 ok(surface_desc.dwHeight == GetSystemMetrics(SM_CYSCREEN), "Expect height %d, got %d.\n",
15181 GetSystemMetrics(SM_CYSCREEN), surface_desc.dwHeight);
15183 DestroyWindow(window);
15184 IDirectDraw2_Release(ddraw);
15185 return TRUE;
15188 static void test_get_display_mode(void)
15190 static const DWORD flags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_REFRESHRATE | DDSD_PIXELFORMAT | DDSD_PITCH;
15191 struct find_different_mode_param param;
15192 DDSURFACEDESC surface_desc;
15193 IDirectDraw2 *ddraw;
15194 DEVMODEW devmode;
15195 HWND window;
15196 HRESULT hr;
15197 BOOL ret;
15199 EnumDisplayMonitors(NULL, NULL, test_get_display_mode_cb, 0);
15201 ddraw = create_ddraw();
15202 ok(!!ddraw, "Failed to create a ddraw object.\n");
15203 window = create_window();
15204 ok(!!window, "Failed to create a window.\n");
15206 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
15207 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
15209 memset(&devmode, 0, sizeof(devmode));
15210 devmode.dmSize = sizeof(devmode);
15211 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
15212 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
15214 surface_desc.dwSize = sizeof(surface_desc);
15215 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
15216 ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr);
15217 ok(surface_desc.dwSize == sizeof(surface_desc), "Expected dwSize %u, got %u.\n",
15218 sizeof(surface_desc), surface_desc.dwSize);
15219 ok(surface_desc.dwFlags == flags, "Expected dwFlags %#x, got %#x.\n", flags,
15220 surface_desc.dwFlags);
15221 ok(surface_desc.dwWidth == devmode.dmPelsWidth, "Expected width %u, got %u.\n",
15222 devmode.dmPelsWidth, surface_desc.dwWidth);
15223 ok(surface_desc.dwHeight == devmode.dmPelsHeight, "Expected height %u, got %u.\n",
15224 devmode.dmPelsHeight, surface_desc.dwHeight);
15225 ok(surface_desc.dwRefreshRate == devmode.dmDisplayFrequency, "Expected frequency %u, got %u.\n",
15226 devmode.dmDisplayFrequency, surface_desc.dwRefreshRate);
15227 ok(surface_desc.ddpfPixelFormat.dwSize == sizeof(surface_desc.ddpfPixelFormat),
15228 "Expected ddpfPixelFormat.dwSize %u, got %u.\n", sizeof(surface_desc.ddpfPixelFormat),
15229 surface_desc.ddpfPixelFormat.dwSize);
15230 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == devmode.dmBitsPerPel,
15231 "Expected ddpfPixelFormat.dwRGBBitCount %u, got %u.\n", devmode.dmBitsPerPel,
15232 surface_desc.ddpfPixelFormat.dwRGBBitCount);
15233 ok(surface_desc.lPitch == devmode.dmPelsWidth * devmode.dmBitsPerPel / 8,
15234 "Expected pitch %u, got %u.\n", devmode.dmPelsWidth * devmode.dmBitsPerPel / 8,
15235 surface_desc.lPitch);
15237 memset(&param, 0, sizeof(param));
15238 param.old_frequency = surface_desc.dwRefreshRate;
15239 hr = IDirectDraw2_EnumDisplayModes(ddraw, DDEDM_REFRESHRATES, NULL, &param,
15240 find_different_mode_callback);
15241 ok(hr == DD_OK, "EnumDisplayModes failed, hr %#x.\n", hr);
15242 if (!param.new_frequency)
15244 skip("Failed to find a display mode with a different frequency.\n");
15245 goto done;
15248 hr = IDirectDraw2_SetDisplayMode(ddraw, param.new_width, param.new_height, param.new_bpp,
15249 param.new_frequency, 0);
15250 ok(hr == DD_OK, "SetDisplayMode failed, hr %#x.\n", hr);
15251 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
15252 ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr);
15253 ok(surface_desc.dwWidth == param.new_width, "Expected width %u, got %u.\n", param.new_width,
15254 surface_desc.dwWidth);
15255 ok(surface_desc.dwHeight == param.new_height, "Expected height %u, got %u.\n", param.new_height,
15256 surface_desc.dwHeight);
15257 ok(surface_desc.dwRefreshRate == param.new_frequency, "Expected frequency %u, got %u.\n",
15258 param.new_frequency, surface_desc.dwRefreshRate);
15259 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == param.new_bpp,
15260 "Expected ddpfPixelFormat.dwRGBBitCount %u, got %u.\n", devmode.dmBitsPerPel,
15261 surface_desc.ddpfPixelFormat.dwRGBBitCount);
15263 done:
15264 DestroyWindow(window);
15265 IDirectDraw2_Release(ddraw);
15268 static void run_for_each_device_type(void (*test_func)(const GUID *))
15270 test_func(&IID_IDirect3DHALDevice);
15271 test_func(&IID_IDirect3DRGBDevice);
15274 START_TEST(ddraw2)
15276 DDDEVICEIDENTIFIER identifier;
15277 DEVMODEW current_mode;
15278 IDirectDraw2 *ddraw;
15279 HMODULE dwmapi;
15281 if (!(ddraw = create_ddraw()))
15283 skip("Failed to create a ddraw object, skipping tests.\n");
15284 return;
15287 if (ddraw_get_identifier(ddraw, &identifier))
15289 trace("Driver string: \"%s\"\n", identifier.szDriver);
15290 trace("Description string: \"%s\"\n", identifier.szDescription);
15291 trace("Driver version %d.%d.%d.%d\n",
15292 HIWORD(U(identifier.liDriverVersion).HighPart), LOWORD(U(identifier.liDriverVersion).HighPart),
15293 HIWORD(U(identifier.liDriverVersion).LowPart), LOWORD(U(identifier.liDriverVersion).LowPart));
15295 IDirectDraw2_Release(ddraw);
15297 memset(&current_mode, 0, sizeof(current_mode));
15298 current_mode.dmSize = sizeof(current_mode);
15299 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
15300 registry_mode.dmSize = sizeof(registry_mode);
15301 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
15302 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
15303 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
15305 skip("Current mode does not match registry mode, skipping test.\n");
15306 return;
15309 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
15310 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
15312 test_coop_level_create_device_window();
15313 test_clipper_blt();
15314 test_coop_level_d3d_state();
15315 test_surface_interface_mismatch();
15316 test_coop_level_threaded();
15317 run_for_each_device_type(test_depth_blit);
15318 test_texture_load_ckey();
15319 test_viewport_object();
15320 test_zenable();
15321 test_ck_rgba();
15322 test_ck_default();
15323 test_ck_complex();
15324 test_surface_qi();
15325 test_device_qi();
15326 test_wndproc();
15327 test_window_style();
15328 test_redundant_mode_set();
15329 test_coop_level_mode_set();
15330 test_coop_level_mode_set_multi();
15331 test_initialize();
15332 test_coop_level_surf_create();
15333 test_coop_level_multi_window();
15334 test_clear_rect_count();
15335 test_coop_level_versions();
15336 test_lighting_interface_versions();
15337 test_coop_level_activateapp();
15338 test_unsupported_formats();
15339 run_for_each_device_type(test_rt_caps);
15340 test_primary_caps();
15341 test_surface_lock();
15342 test_surface_discard();
15343 test_flip();
15344 test_set_surface_desc();
15345 test_user_memory_getdc();
15346 test_sysmem_overlay();
15347 test_primary_palette();
15348 test_surface_attachment();
15349 test_pixel_format();
15350 test_create_surface_pitch();
15351 test_mipmap();
15352 test_palette_complex();
15353 test_p8_blit();
15354 test_material();
15355 test_lighting();
15356 test_specular_lighting();
15357 test_palette_gdi();
15358 test_palette_alpha();
15359 test_lost_device();
15360 test_surface_desc_lock();
15361 test_texturemapblend();
15362 test_viewport_clear_rect();
15363 test_color_fill();
15364 test_colorkey_precision();
15365 test_range_colorkey();
15366 test_shademode();
15367 test_lockrect_invalid();
15368 test_yv12_overlay();
15369 test_offscreen_overlay();
15370 test_overlay_rect();
15371 test_blt();
15372 test_blt_z_alpha();
15373 test_cross_device_blt();
15374 test_getdc();
15375 test_draw_primitive();
15376 test_edge_antialiasing_blending();
15377 test_transform_vertices();
15378 test_display_mode_surface_pixel_format();
15379 test_surface_desc_size();
15380 test_ck_operation();
15381 test_set_render_state();
15382 test_depth_readback();
15383 test_clear();
15384 test_enum_surfaces();
15385 test_viewport();
15386 test_find_device();
15387 test_killfocus();
15388 test_gdi_surface();
15389 test_alphatest();
15390 test_clipper_refcount();
15391 test_caps();
15392 test_d32_support();
15393 test_cursor_clipping();
15394 test_window_position();
15395 test_get_display_mode();