ddraw/tests: Do not create a fullscreen test window in test_window_position_cb().
[wine.git] / dlls / ddraw / tests / ddraw4.c
blobff38483faf9007663e70f2a20d59078ce92e23fc
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 #define COBJMACROS
23 #include "wine/test.h"
24 #include "wine/heap.h"
25 #include <limits.h>
26 #include <math.h>
27 #include "ddrawi.h"
28 #include "d3dhal.h"
30 HRESULT WINAPI GetSurfaceFromDC(HDC dc, struct IDirectDrawSurface **surface, HDC *device_dc);
32 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
33 static DEVMODEW registry_mode;
35 static HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *);
37 struct vec2
39 float x, y;
42 struct vec3
44 float x, y, z;
47 struct vec4
49 float x, y, z, w;
52 struct create_window_thread_param
54 HWND window;
55 HANDLE window_created;
56 HANDLE destroy_window;
57 HANDLE thread;
60 static BOOL compare_float(float f, float g, unsigned int ulps)
62 int x = *(int *)&f;
63 int y = *(int *)&g;
65 if (x < 0)
66 x = INT_MIN - x;
67 if (y < 0)
68 y = INT_MIN - y;
70 if (abs(x - y) > ulps)
71 return FALSE;
73 return TRUE;
76 static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
78 return compare_float(vec->x, x, ulps)
79 && compare_float(vec->y, y, ulps)
80 && compare_float(vec->z, z, ulps)
81 && compare_float(vec->w, w, ulps);
84 static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff)
86 unsigned int diff = x > y ? x - y : y - x;
88 return diff <= max_diff;
91 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
93 return compare_uint(c1 & 0xff, c2 & 0xff, max_diff)
94 && compare_uint((c1 >> 8) & 0xff, (c2 >> 8) & 0xff, max_diff)
95 && compare_uint((c1 >> 16) & 0xff, (c2 >> 16) & 0xff, max_diff)
96 && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff);
99 static void get_virtual_rect(RECT *rect)
101 rect->left = GetSystemMetrics(SM_XVIRTUALSCREEN);
102 rect->top = GetSystemMetrics(SM_YVIRTUALSCREEN);
103 rect->right = rect->left + GetSystemMetrics(SM_CXVIRTUALSCREEN);
104 rect->bottom = rect->top + GetSystemMetrics(SM_CYVIRTUALSCREEN);
107 /* Try to make sure pending X events have been processed before continuing */
108 static void flush_events(void)
110 int diff = 200;
111 DWORD time;
112 MSG msg;
114 time = GetTickCount() + diff;
115 while (diff > 0)
117 if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT)
118 break;
119 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
120 DispatchMessageA(&msg);
121 diff = time - GetTickCount();
125 static BOOL ddraw_get_identifier(IDirectDraw4 *ddraw, DDDEVICEIDENTIFIER *identifier)
127 HRESULT hr;
129 hr = IDirectDraw4_GetDeviceIdentifier(ddraw, identifier, 0);
130 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#lx.\n", hr);
132 return SUCCEEDED(hr);
135 static BOOL ddraw_is_warp(IDirectDraw4 *ddraw)
137 DDDEVICEIDENTIFIER identifier;
139 return strcmp(winetest_platform, "wine")
140 && ddraw_get_identifier(ddraw, &identifier)
141 && strstr(identifier.szDriver, "warp");
144 static BOOL ddraw_is_vendor(IDirectDraw4 *ddraw, DWORD vendor)
146 DDDEVICEIDENTIFIER identifier;
148 return strcmp(winetest_platform, "wine")
149 && ddraw_get_identifier(ddraw, &identifier)
150 && identifier.dwVendorId == vendor;
153 static BOOL ddraw_is_amd(IDirectDraw4 *ddraw)
155 return ddraw_is_vendor(ddraw, 0x1002);
158 static BOOL ddraw_is_intel(IDirectDraw4 *ddraw)
160 return ddraw_is_vendor(ddraw, 0x8086);
163 static BOOL ddraw_is_nvidia(IDirectDraw4 *ddraw)
165 return ddraw_is_vendor(ddraw, 0x10de);
168 static BOOL ddraw_is_vmware(IDirectDraw4 *ddraw)
170 return ddraw_is_vendor(ddraw, 0x15ad);
173 static BOOL is_software_device_type(const GUID *device_guid)
175 return device_guid != &IID_IDirect3DHALDevice;
178 static IDirectDrawSurface4 *create_overlay(IDirectDraw4 *ddraw,
179 unsigned int width, unsigned int height, DWORD format)
181 IDirectDrawSurface4 *surface;
182 DDSURFACEDESC2 desc;
184 memset(&desc, 0, sizeof(desc));
185 desc.dwSize = sizeof(desc);
186 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
187 desc.dwWidth = width;
188 desc.dwHeight = height;
189 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
190 U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat);
191 U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
192 U4(desc).ddpfPixelFormat.dwFourCC = format;
194 if (FAILED(IDirectDraw4_CreateSurface(ddraw, &desc, &surface, NULL)))
195 return NULL;
196 return surface;
199 static HWND create_window(void)
201 RECT r = {0, 0, 640, 480};
203 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
205 return CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
206 CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
209 static DWORD WINAPI create_window_thread_proc(void *param)
211 struct create_window_thread_param *p = param;
212 DWORD res;
213 BOOL ret;
215 p->window = create_window();
216 ret = SetEvent(p->window_created);
217 ok(ret, "SetEvent failed, last error %lu.\n", GetLastError());
219 for (;;)
221 MSG msg;
223 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
224 DispatchMessageA(&msg);
225 res = WaitForSingleObject(p->destroy_window, 100);
226 if (res == WAIT_OBJECT_0)
227 break;
228 if (res != WAIT_TIMEOUT)
230 ok(0, "Wait failed (%#lx), last error %lu.\n", res, GetLastError());
231 break;
235 DestroyWindow(p->window);
237 return 0;
240 static void create_window_thread(struct create_window_thread_param *p)
242 DWORD res, tid;
244 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
245 ok(!!p->window_created, "CreateEvent failed, last error %lu.\n", GetLastError());
246 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
247 ok(!!p->destroy_window, "CreateEvent failed, last error %lu.\n", GetLastError());
248 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
249 ok(!!p->thread, "Failed to create thread, last error %lu.\n", GetLastError());
250 res = WaitForSingleObject(p->window_created, INFINITE);
251 ok(res == WAIT_OBJECT_0, "Wait failed (%#lx), last error %lu.\n", res, GetLastError());
254 static void destroy_window_thread(struct create_window_thread_param *p)
256 SetEvent(p->destroy_window);
257 WaitForSingleObject(p->thread, INFINITE);
258 CloseHandle(p->destroy_window);
259 CloseHandle(p->window_created);
260 CloseHandle(p->thread);
263 static IDirectDrawSurface4 *get_depth_stencil(IDirect3DDevice3 *device)
265 IDirectDrawSurface4 *rt, *ret;
266 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, {0}};
267 HRESULT hr;
269 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
270 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#lx.\n", hr);
271 hr = IDirectDrawSurface4_GetAttachedSurface(rt, &caps, &ret);
272 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#lx.\n", hr);
273 IDirectDrawSurface4_Release(rt);
274 return ret;
277 /* Free original_modes after finished using it */
278 static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
280 unsigned int number, size = 2, count = 0, index = 0;
281 DISPLAY_DEVICEW display_device;
282 DEVMODEW *modes, *tmp;
284 if (!(modes = heap_alloc(size * sizeof(*modes))))
285 return FALSE;
287 display_device.cb = sizeof(display_device);
288 while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
290 /* Skip software devices */
291 if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
292 continue;
294 if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
295 continue;
297 if (count >= size)
299 size *= 2;
300 if (!(tmp = heap_realloc(modes, size * sizeof(*modes))))
302 heap_free(modes);
303 return FALSE;
305 modes = tmp;
308 memset(&modes[count], 0, sizeof(modes[count]));
309 modes[count].dmSize = sizeof(modes[count]);
310 if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
312 heap_free(modes);
313 return FALSE;
316 lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
319 *original_modes = modes;
320 *display_count = count;
321 return TRUE;
324 static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
326 unsigned int index;
327 LONG ret;
329 for (index = 0; index < count; ++index)
331 ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
332 CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
333 if (ret != DISP_CHANGE_SUCCESSFUL)
334 return FALSE;
336 ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
337 return ret == DISP_CHANGE_SUCCESSFUL;
340 static HRESULT set_display_mode(IDirectDraw4 *ddraw, DWORD width, DWORD height)
342 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
343 return DD_OK;
344 return IDirectDraw4_SetDisplayMode(ddraw, width, height, 24, 0, 0);
347 static D3DCOLOR get_surface_color(IDirectDrawSurface4 *surface, UINT x, UINT y)
349 RECT rect = {x, y, x + 1, y + 1};
350 DDSURFACEDESC2 surface_desc;
351 D3DCOLOR color;
352 HRESULT hr;
354 memset(&surface_desc, 0, sizeof(surface_desc));
355 surface_desc.dwSize = sizeof(surface_desc);
357 hr = IDirectDrawSurface4_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
358 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
359 if (FAILED(hr))
360 return 0xdeadbeef;
362 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
364 hr = IDirectDrawSurface4_Unlock(surface, &rect);
365 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
367 return color;
370 static void fill_surface(IDirectDrawSurface4 *surface, D3DCOLOR color)
372 DDSURFACEDESC2 surface_desc = {sizeof(surface_desc)};
373 HRESULT hr;
374 unsigned int x, y;
375 DWORD *ptr;
377 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
378 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
380 for (y = 0; y < surface_desc.dwHeight; ++y)
382 ptr = (DWORD *)((BYTE *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
383 for (x = 0; x < surface_desc.dwWidth; ++x)
385 ptr[x] = color;
389 hr = IDirectDrawSurface4_Unlock(surface, NULL);
390 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
393 static void check_rect(IDirectDrawSurface4 *surface, RECT r)
395 LONG x_coords[2][2] =
397 {r.left - 1, r.left + 1},
398 {r.right + 1, r.right - 1},
400 LONG y_coords[2][2] =
402 {r.top - 1, r.top + 1},
403 {r.bottom + 1, r.bottom - 1}
405 unsigned int color, i, j, x_side, y_side;
406 LONG x, y;
408 for (i = 0; i < 2; ++i)
410 for (j = 0; j < 2; ++j)
412 for (x_side = 0; x_side < 2; ++x_side)
414 for (y_side = 0; y_side < 2; ++y_side)
416 unsigned int expected = (x_side == 1 && y_side == 1) ? 0x00ffffff : 0x00000000;
418 x = x_coords[i][x_side];
419 y = y_coords[j][y_side];
420 if (x < 0 || x >= 640 || y < 0 || y >= 480)
421 continue;
422 color = get_surface_color(surface, x, y);
423 ok(color == expected, "Pixel (%ld, %ld) has color %08x, expected %08x.\n", x, y, color, expected);
430 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
432 DDPIXELFORMAT *z_fmt = ctx;
434 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
435 *z_fmt = *format;
437 return DDENUMRET_OK;
440 static IDirectDraw4 *create_ddraw(void)
442 IDirectDraw4 *ddraw4;
443 IDirectDraw *ddraw1;
444 HRESULT hr;
446 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
447 return NULL;
449 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4);
450 IDirectDraw_Release(ddraw1);
451 if (FAILED(hr))
452 return NULL;
454 return ddraw4;
457 static IDirect3DDevice3 *create_device_ex(HWND window, DWORD coop_level, const GUID *device_guid)
459 IDirectDrawSurface4 *surface, *ds;
460 IDirect3DDevice3 *device = NULL;
461 DDSURFACEDESC2 surface_desc;
462 IDirectDraw4 *ddraw4;
463 DDPIXELFORMAT z_fmt;
464 IDirect3D3 *d3d3;
465 HRESULT hr;
467 if (!(ddraw4 = create_ddraw()))
468 return NULL;
470 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, coop_level);
471 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
473 memset(&surface_desc, 0, sizeof(surface_desc));
474 surface_desc.dwSize = sizeof(surface_desc);
475 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
476 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
477 if (is_software_device_type(device_guid))
478 surface_desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
479 surface_desc.dwWidth = 640;
480 surface_desc.dwHeight = 480;
482 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &surface, NULL);
483 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
485 if (coop_level & DDSCL_NORMAL)
487 IDirectDrawClipper *clipper;
489 hr = IDirectDraw4_CreateClipper(ddraw4, 0, &clipper, NULL);
490 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
491 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
492 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
493 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
494 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#lx.\n", hr);
495 IDirectDrawClipper_Release(clipper);
498 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirect3D3, (void **)&d3d3);
499 IDirectDraw4_Release(ddraw4);
500 if (FAILED(hr))
502 IDirectDrawSurface4_Release(surface);
503 return NULL;
506 memset(&z_fmt, 0, sizeof(z_fmt));
507 hr = IDirect3D3_EnumZBufferFormats(d3d3, device_guid, enum_z_fmt, &z_fmt);
508 if (FAILED(hr) || !z_fmt.dwSize)
510 IDirect3D3_Release(d3d3);
511 IDirectDrawSurface4_Release(surface);
512 return NULL;
515 memset(&surface_desc, 0, sizeof(surface_desc));
516 surface_desc.dwSize = sizeof(surface_desc);
517 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
518 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
519 if (is_software_device_type(device_guid))
520 surface_desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
522 U4(surface_desc).ddpfPixelFormat = z_fmt;
523 surface_desc.dwWidth = 640;
524 surface_desc.dwHeight = 480;
525 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &ds, NULL);
526 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#lx.\n", hr);
527 if (FAILED(hr))
529 IDirect3D3_Release(d3d3);
530 IDirectDrawSurface4_Release(surface);
531 return NULL;
534 hr = IDirectDrawSurface4_AddAttachedSurface(surface, ds);
535 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#lx.\n", hr);
536 IDirectDrawSurface4_Release(ds);
537 if (FAILED(hr))
539 IDirect3D3_Release(d3d3);
540 IDirectDrawSurface4_Release(surface);
541 return NULL;
544 hr = IDirect3D3_CreateDevice(d3d3, device_guid, surface, &device, NULL);
545 IDirect3D3_Release(d3d3);
546 IDirectDrawSurface4_Release(surface);
547 if (FAILED(hr))
548 return NULL;
550 return device;
553 static IDirect3DDevice3 *create_device(HWND window, DWORD coop_level)
555 return create_device_ex(window, coop_level, &IID_IDirect3DHALDevice);
558 static IDirect3DViewport3 *create_viewport(IDirect3DDevice3 *device, UINT x, UINT y, UINT w, UINT h)
560 IDirect3DViewport3 *viewport;
561 D3DVIEWPORT2 vp;
562 IDirect3D3 *d3d;
563 HRESULT hr;
565 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
566 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
567 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
568 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#lx.\n", hr);
569 hr = IDirect3DDevice3_AddViewport(device, viewport);
570 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#lx.\n", hr);
571 memset(&vp, 0, sizeof(vp));
572 vp.dwSize = sizeof(vp);
573 vp.dwX = x;
574 vp.dwY = y;
575 vp.dwWidth = w;
576 vp.dwHeight = h;
577 vp.dvClipX = -1.0f;
578 vp.dvClipY = 1.0f;
579 vp.dvClipWidth = 2.0f;
580 vp.dvClipHeight = 2.0f;
581 vp.dvMinZ = 0.0f;
582 vp.dvMaxZ = 1.0f;
583 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
584 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#lx.\n", hr);
585 IDirect3D3_Release(d3d);
587 return viewport;
590 static void destroy_viewport(IDirect3DDevice3 *device, IDirect3DViewport3 *viewport)
592 HRESULT hr;
594 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
595 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#lx.\n", hr);
596 IDirect3DViewport3_Release(viewport);
599 static IDirect3DMaterial3 *create_material(IDirect3DDevice3 *device, D3DMATERIAL *mat)
601 IDirect3DMaterial3 *material;
602 IDirect3D3 *d3d;
603 HRESULT hr;
605 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
606 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
607 hr = IDirect3D3_CreateMaterial(d3d, &material, NULL);
608 ok(SUCCEEDED(hr), "Failed to create material, hr %#lx.\n", hr);
609 hr = IDirect3DMaterial3_SetMaterial(material, mat);
610 ok(SUCCEEDED(hr), "Failed to set material data, hr %#lx.\n", hr);
611 IDirect3D3_Release(d3d);
613 return material;
616 static IDirect3DMaterial3 *create_diffuse_material(IDirect3DDevice3 *device, float r, float g, float b, float a)
618 D3DMATERIAL mat;
620 memset(&mat, 0, sizeof(mat));
621 mat.dwSize = sizeof(mat);
622 U1(U(mat).diffuse).r = r;
623 U2(U(mat).diffuse).g = g;
624 U3(U(mat).diffuse).b = b;
625 U4(U(mat).diffuse).a = a;
627 return create_material(device, &mat);
630 static IDirect3DMaterial3 *create_diffuse_and_ambient_material(IDirect3DDevice3 *device,
631 float r, float g, float b, float a)
633 D3DMATERIAL mat;
635 memset(&mat, 0, sizeof(mat));
636 mat.dwSize = sizeof(mat);
637 U1(U(mat).diffuse).r = r;
638 U2(U(mat).diffuse).g = g;
639 U3(U(mat).diffuse).b = b;
640 U4(U(mat).diffuse).a = a;
642 U1(U(mat).ambient).r = r;
643 U2(U(mat).ambient).g = g;
644 U3(U(mat).ambient).b = b;
645 U4(U(mat).ambient).a = a;
647 return create_material(device, &mat);
650 static IDirect3DMaterial3 *create_specular_material(IDirect3DDevice3 *device,
651 float r, float g, float b, float a, float power)
653 D3DMATERIAL mat;
655 memset(&mat, 0, sizeof(mat));
656 mat.dwSize = sizeof(mat);
657 U1(U2(mat).specular).r = r;
658 U2(U2(mat).specular).g = g;
659 U3(U2(mat).specular).b = b;
660 U4(U2(mat).specular).a = a;
661 U4(mat).power = power;
663 return create_material(device, &mat);
666 static IDirect3DMaterial3 *create_emissive_material(IDirect3DDevice3 *device, float r, float g, float b, float a)
668 D3DMATERIAL mat;
670 memset(&mat, 0, sizeof(mat));
671 mat.dwSize = sizeof(mat);
672 U1(U3(mat).emissive).r = r;
673 U2(U3(mat).emissive).g = g;
674 U3(U3(mat).emissive).b = b;
675 U4(U3(mat).emissive).a = a;
677 return create_material(device, &mat);
680 static void destroy_material(IDirect3DMaterial3 *material)
682 IDirect3DMaterial3_Release(material);
685 struct message
687 UINT message;
688 BOOL check_wparam;
689 WPARAM expect_wparam;
690 HRESULT ddraw_state;
693 static const struct message *expect_messages;
694 static IDirectDraw4 *focus_test_ddraw;
696 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
698 HRESULT hr;
700 if (expect_messages && message == expect_messages->message)
702 if (expect_messages->check_wparam)
703 ok (wparam == expect_messages->expect_wparam,
704 "Got unexpected wparam %#Ix for message %#x, expected %#Ix.\n",
705 wparam, message, expect_messages->expect_wparam);
707 if (focus_test_ddraw)
709 hr = IDirectDraw4_TestCooperativeLevel(focus_test_ddraw);
710 ok(hr == expect_messages->ddraw_state, "Got ddraw state %#lx on message %#x, expected %#lx.\n",
711 hr, message, expect_messages->ddraw_state);
714 ++expect_messages;
717 return DefWindowProcA(hwnd, message, wparam, lparam);
720 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
721 * interface. This prevents subsequent SetCooperativeLevel() calls on a
722 * different window from failing with DDERR_HWNDALREADYSET. */
723 static void fix_wndproc(HWND window, LONG_PTR proc)
725 IDirectDraw4 *ddraw;
726 HRESULT hr;
728 if (!(ddraw = create_ddraw()))
729 return;
731 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
732 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
733 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
734 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
735 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
737 IDirectDraw4_Release(ddraw);
740 static void test_process_vertices(void)
742 IDirect3DVertexBuffer *src_vb, *dst_vb;
743 IDirect3DViewport3 *viewport;
744 D3DVERTEXBUFFERDESC vb_desc;
745 IDirect3DDevice3 *device;
746 struct vec3 *src_data;
747 struct vec4 *dst_data;
748 IDirect3D3 *d3d3;
749 D3DVIEWPORT2 vp2;
750 D3DVIEWPORT vp1;
751 HWND window;
752 HRESULT hr;
754 static D3DMATRIX identity =
756 1.0f, 0.0f, 0.0f, 0.0f,
757 0.0f, 1.0f, 0.0f, 0.0f,
758 0.0f, 0.0f, 1.0f, 0.0f,
759 0.0f, 0.0f, 0.0f, 1.0f,
761 static D3DMATRIX projection =
763 1.0f, 0.0f, 0.0f, 0.0f,
764 0.0f, 1.0f, 0.0f, 0.0f,
765 0.0f, 0.0f, 1.0f, 0.0f,
766 6.0f, 7.0f, 8.0f, 1.0f,
769 window = create_window();
770 if (!(device = create_device(window, DDSCL_NORMAL)))
772 skip("Failed to create a 3D device, skipping test.\n");
773 DestroyWindow(window);
774 return;
777 hr = IDirect3DDevice3_GetDirect3D(device, &d3d3);
778 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#lx.\n", hr);
780 memset(&vb_desc, 0, sizeof(vb_desc));
781 vb_desc.dwSize = sizeof(vb_desc);
782 vb_desc.dwFVF = D3DFVF_XYZ;
783 vb_desc.dwNumVertices = 3;
784 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &src_vb, 0, NULL);
785 ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#lx.\n", hr);
787 hr = IDirect3DVertexBuffer_Lock(src_vb, DDLOCK_WRITEONLY, (void **)&src_data, NULL);
788 ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#lx.\n", hr);
789 src_data[0].x = -1.0f;
790 src_data[0].y = -1.0f;
791 src_data[0].z = -1.0f;
792 src_data[1].x = 0.0f;
793 src_data[1].y = 0.0f;
794 src_data[1].z = 0.0f;
795 src_data[2].x = 1.0f;
796 src_data[2].y = 1.0f;
797 src_data[2].z = 1.0f;
798 hr = IDirect3DVertexBuffer_Unlock(src_vb);
799 ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#lx.\n", hr);
801 memset(&vb_desc, 0, sizeof(vb_desc));
802 vb_desc.dwSize = sizeof(vb_desc);
803 vb_desc.dwFVF = D3DFVF_XYZRHW;
804 vb_desc.dwNumVertices = 3;
805 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &dst_vb, 0, NULL);
806 ok(SUCCEEDED(hr), "Failed to create destination vertex buffer, hr %#lx.\n", hr);
808 hr = IDirect3D3_CreateViewport(d3d3, &viewport, NULL);
809 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#lx.\n", hr);
810 hr = IDirect3DDevice3_AddViewport(device, viewport);
811 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#lx.\n", hr);
812 vp2.dwSize = sizeof(vp2);
813 vp2.dwX = 10;
814 vp2.dwY = 20;
815 vp2.dwWidth = 100;
816 vp2.dwHeight = 200;
817 vp2.dvClipX = 2.0f;
818 vp2.dvClipY = 3.0f;
819 vp2.dvClipWidth = 4.0f;
820 vp2.dvClipHeight = 5.0f;
821 vp2.dvMinZ = -2.0f;
822 vp2.dvMaxZ = 3.0f;
823 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
824 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#lx.\n", hr);
825 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
826 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
828 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
829 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#lx.\n", hr);
830 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &identity);
831 ok(SUCCEEDED(hr), "Failed to set view transformation, hr %#lx.\n", hr);
832 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
833 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#lx.\n", hr);
835 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
836 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#lx.\n", hr);
838 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
839 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#lx.\n", hr);
840 ok(compare_vec4(&dst_data[0], -6.500e+1f, +1.800e+2f, +2.000e-1f, +1.000e+0f, 4096),
841 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
842 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
843 ok(compare_vec4(&dst_data[1], -4.000e+1f, +1.400e+2f, +4.000e-1f, +1.000e+0f, 4096),
844 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
845 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
846 ok(compare_vec4(&dst_data[2], -1.500e+1f, +1.000e+2f, +6.000e-1f, +1.000e+0f, 4096),
847 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
848 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
849 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
850 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#lx.\n", hr);
852 hr = IDirect3DDevice3_MultiplyTransform(device, D3DTRANSFORMSTATE_PROJECTION, &projection);
853 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#lx.\n", hr);
855 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
856 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#lx.\n", hr);
858 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
859 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#lx.\n", hr);
860 ok(compare_vec4(&dst_data[0], +8.500e+1f, -1.000e+2f, +1.800e+0f, +1.000e+0f, 4096),
861 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
862 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
863 ok(compare_vec4(&dst_data[1], +1.100e+2f, -1.400e+2f, +2.000e+0f, +1.000e+0f, 4096),
864 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
865 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
866 ok(compare_vec4(&dst_data[2], +1.350e+2f, -1.800e+2f, +2.200e+0f, +1.000e+0f, 4096),
867 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
868 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
869 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
870 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#lx.\n", hr);
872 vp2.dwSize = sizeof(vp2);
873 vp2.dwX = 30;
874 vp2.dwY = 40;
875 vp2.dwWidth = 90;
876 vp2.dwHeight = 80;
877 vp2.dvClipX = 4.0f;
878 vp2.dvClipY = 6.0f;
879 vp2.dvClipWidth = 2.0f;
880 vp2.dvClipHeight = 4.0f;
881 vp2.dvMinZ = 3.0f;
882 vp2.dvMaxZ = -2.0f;
883 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
884 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#lx.\n", hr);
886 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
887 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#lx.\n", hr);
889 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
890 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#lx.\n", hr);
891 ok(compare_vec4(&dst_data[0], +7.500e+1f, +4.000e+1f, -8.000e-1f, +1.000e+0f, 4096),
892 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
893 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
894 ok(compare_vec4(&dst_data[1], +1.200e+2f, +2.000e+1f, -1.000e+0f, +1.000e+0f, 4096),
895 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
896 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
897 ok(compare_vec4(&dst_data[2], +1.650e+2f, +0.000e+0f, -1.200e+0f, +1.000e+0f, 4096),
898 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
899 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
900 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
901 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#lx.\n", hr);
903 vp1.dwSize = sizeof(vp1);
904 vp1.dwX = 30;
905 vp1.dwY = 40;
906 vp1.dwWidth = 90;
907 vp1.dwHeight = 80;
908 vp1.dvScaleX = 7.0f;
909 vp1.dvScaleY = 2.0f;
910 vp1.dvMaxX = 6.0f;
911 vp1.dvMaxY = 10.0f;
912 vp1.dvMinZ = -2.0f;
913 vp1.dvMaxZ = 3.0f;
914 hr = IDirect3DViewport3_SetViewport(viewport, &vp1);
915 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#lx.\n", hr);
917 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
918 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#lx.\n", hr);
920 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
921 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#lx.\n", hr);
922 ok(compare_vec4(&dst_data[0], +1.100e+2f, +6.800e+1f, +7.000e+0f, +1.000e+0f, 4096),
923 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
924 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
925 ok(compare_vec4(&dst_data[1], +1.170e+2f, +6.600e+1f, +8.000e+0f, +1.000e+0f, 4096),
926 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
927 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
928 ok(compare_vec4(&dst_data[2], +1.240e+2f, +6.400e+1f, +9.000e+0f, +1.000e+0f, 4096),
929 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
930 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
931 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
932 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#lx.\n", hr);
934 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
935 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#lx.\n", hr);
937 IDirect3DVertexBuffer_Release(dst_vb);
938 IDirect3DVertexBuffer_Release(src_vb);
939 IDirect3DViewport3_Release(viewport);
940 IDirect3D3_Release(d3d3);
941 IDirect3DDevice3_Release(device);
942 DestroyWindow(window);
945 static void test_coop_level_create_device_window(void)
947 HWND focus_window, device_window;
948 IDirectDraw4 *ddraw;
949 HRESULT hr;
951 focus_window = create_window();
952 ddraw = create_ddraw();
953 ok(!!ddraw, "Failed to create a ddraw object.\n");
955 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
956 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
957 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
958 ok(!device_window, "Unexpected device window found.\n");
959 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
960 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
961 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
962 ok(!device_window, "Unexpected device window found.\n");
963 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
964 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
965 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
966 ok(!device_window, "Unexpected device window found.\n");
967 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
968 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
969 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
970 ok(!device_window, "Unexpected device window found.\n");
971 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
972 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#lx.\n", hr);
973 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
974 ok(!device_window, "Unexpected device window found.\n");
976 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
977 if (broken(hr == DDERR_INVALIDPARAMS))
979 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
980 IDirectDraw4_Release(ddraw);
981 DestroyWindow(focus_window);
982 return;
985 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
986 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
987 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
988 ok(!device_window, "Unexpected device window found.\n");
989 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
990 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
991 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
992 ok(!device_window, "Unexpected device window found.\n");
994 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
995 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
996 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
997 ok(!device_window, "Unexpected device window found.\n");
998 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
999 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1000 ok(hr == DDERR_NOHWND, "Got unexpected hr %#lx.\n", hr);
1001 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
1002 ok(!!device_window, "Device window not found.\n");
1004 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1005 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1006 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
1007 ok(!device_window, "Unexpected device window found.\n");
1008 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
1009 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1010 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1011 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
1012 ok(!!device_window, "Device window not found.\n");
1014 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1015 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1016 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
1017 ok(!device_window, "Unexpected device window found.\n");
1018 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1019 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#lx.\n", hr);
1020 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
1021 ok(!device_window, "Unexpected device window found.\n");
1022 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
1023 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1024 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
1025 ok(!device_window, "Unexpected device window found.\n");
1026 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1027 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1028 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
1029 ok(!!device_window, "Device window not found.\n");
1031 IDirectDraw4_Release(ddraw);
1032 DestroyWindow(focus_window);
1035 static void test_clipper_blt(void)
1037 IDirectDrawSurface4 *src_surface, *dst_surface;
1038 unsigned int color, i, j, x, y;
1039 RECT client_rect, src_rect;
1040 IDirectDrawClipper *clipper;
1041 DDSURFACEDESC2 surface_desc;
1042 IDirectDraw4 *ddraw;
1043 RGNDATA *rgn_data;
1044 ULONG refcount;
1045 HRGN r1, r2;
1046 HWND window;
1047 DDBLTFX fx;
1048 HRESULT hr;
1049 DWORD *ptr;
1050 DWORD ret;
1052 static const DWORD src_data[] =
1054 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
1055 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
1056 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
1058 static const unsigned int expected1[] =
1060 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
1061 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
1062 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
1063 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
1065 /* Nvidia on Windows seems to have an off-by-one error
1066 * when processing source rectangles. Our left = 1 and
1067 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
1068 * read as well, but only for the edge pixels on the
1069 * output image. The bug happens on the y axis as well,
1070 * but we only read one row there, and all source rows
1071 * contain the same data. This bug is not dependent on
1072 * the presence of a clipper. */
1073 static const D3DCOLOR expected1_broken[] =
1075 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
1076 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
1077 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
1078 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
1080 static const unsigned int expected2[] =
1082 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
1083 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
1084 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
1085 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
1088 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1089 10, 10, 640, 480, 0, 0, 0, 0);
1090 ShowWindow(window, SW_SHOW);
1091 ddraw = create_ddraw();
1092 ok(!!ddraw, "Failed to create a ddraw object.\n");
1094 ret = GetClientRect(window, &client_rect);
1095 ok(ret, "Failed to get client rect.\n");
1096 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
1097 ok(ret, "Failed to map client rect.\n");
1099 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1100 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
1102 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
1103 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
1104 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1105 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#lx.\n", hr);
1106 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
1107 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
1108 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1109 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#lx.\n", hr);
1110 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
1111 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
1112 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#lx.\n", hr);
1113 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#lx.\n", rgn_data->rdh.dwSize);
1114 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#lx.\n", rgn_data->rdh.iType);
1115 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %lu.\n", rgn_data->rdh.nCount);
1116 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
1117 "Got unexpected bounding rect %s, expected %s.\n",
1118 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
1119 HeapFree(GetProcessHeap(), 0, rgn_data);
1121 r1 = CreateRectRgn(0, 0, 320, 240);
1122 ok(!!r1, "Failed to create region.\n");
1123 r2 = CreateRectRgn(320, 240, 640, 480);
1124 ok(!!r2, "Failed to create region.\n");
1125 CombineRgn(r1, r1, r2, RGN_OR);
1126 ret = GetRegionData(r1, 0, NULL);
1127 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
1128 ret = GetRegionData(r1, ret, rgn_data);
1129 ok(!!ret, "Failed to get region data.\n");
1131 DeleteObject(r2);
1132 DeleteObject(r1);
1134 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
1135 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#lx.\n", hr);
1136 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
1137 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
1138 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
1139 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#lx.\n", hr);
1141 HeapFree(GetProcessHeap(), 0, rgn_data);
1143 memset(&surface_desc, 0, sizeof(surface_desc));
1144 surface_desc.dwSize = sizeof(surface_desc);
1145 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1146 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1147 surface_desc.dwWidth = 640;
1148 surface_desc.dwHeight = 480;
1149 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1150 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1151 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1152 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1153 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1154 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1156 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
1157 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#lx.\n", hr);
1158 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
1159 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#lx.\n", hr);
1161 memset(&fx, 0, sizeof(fx));
1162 fx.dwSize = sizeof(fx);
1163 hr = IDirectDrawSurface4_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1164 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#lx.\n", hr);
1165 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1166 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#lx.\n", hr);
1168 hr = IDirectDrawSurface4_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
1169 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#lx.\n", hr);
1170 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %lu.\n", U1(surface_desc).lPitch);
1171 ptr = surface_desc.lpSurface;
1172 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
1173 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
1174 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
1175 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
1176 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#lx.\n", hr);
1178 hr = IDirectDrawSurface4_SetClipper(dst_surface, clipper);
1179 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
1181 SetRect(&src_rect, 1, 1, 5, 2);
1182 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
1183 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
1184 for (i = 0; i < 4; ++i)
1186 for (j = 0; j < 4; ++j)
1188 x = 80 * ((2 * j) + 1);
1189 y = 60 * ((2 * i) + 1);
1190 color = get_surface_color(dst_surface, x, y);
1191 ok(compare_color(color, expected1[i * 4 + j], 1)
1192 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
1193 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
1197 U5(fx).dwFillColor = 0xff0000ff;
1198 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1199 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#lx.\n", hr);
1200 for (i = 0; i < 4; ++i)
1202 for (j = 0; j < 4; ++j)
1204 x = 80 * ((2 * j) + 1);
1205 y = 60 * ((2 * i) + 1);
1206 color = get_surface_color(dst_surface, x, y);
1207 ok(compare_color(color, expected2[i * 4 + j], 1),
1208 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
1212 hr = IDirectDrawSurface4_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
1213 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#lx.\n", hr);
1215 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
1216 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
1217 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1218 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#lx.\n", hr);
1219 DestroyWindow(window);
1220 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1221 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
1222 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
1223 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
1224 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1225 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#lx.\n", hr);
1226 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
1227 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#lx.\n", hr);
1228 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1229 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#lx.\n", hr);
1230 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1231 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#lx.\n", hr);
1233 IDirectDrawSurface4_Release(dst_surface);
1234 IDirectDrawSurface4_Release(src_surface);
1235 refcount = IDirectDrawClipper_Release(clipper);
1236 ok(!refcount, "Clipper has %lu references left.\n", refcount);
1237 IDirectDraw4_Release(ddraw);
1240 static void test_coop_level_d3d_state(void)
1242 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1243 IDirectDrawSurface4 *rt, *surface;
1244 IDirect3DViewport3 *viewport;
1245 IDirect3DDevice3 *device;
1246 IDirectDraw4 *ddraw;
1247 DDSURFACEDESC2 lock;
1248 unsigned int color;
1249 IDirect3D3 *d3d;
1250 DWORD value;
1251 HWND window;
1252 HRESULT hr;
1254 static struct
1256 struct vec3 position;
1257 DWORD diffuse;
1259 quad[] =
1261 {{-1.0f, -1.0f, 0.0f}, 0x800000ff},
1262 {{-1.0f, 1.0f, 0.0f}, 0x800000ff},
1263 {{ 1.0f, -1.0f, 0.0f}, 0x800000ff},
1264 {{ 1.0f, 1.0f, 0.0f}, 0x800000ff},
1267 window = create_window();
1268 if (!(device = create_device(window, DDSCL_NORMAL)))
1270 skip("Failed to create a 3D device, skipping test.\n");
1271 DestroyWindow(window);
1272 return;
1275 viewport = create_viewport(device, 0, 0, 640, 480);
1277 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1278 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1279 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
1280 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1282 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1283 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1284 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1285 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1286 ok(!!value, "Got unexpected z-enable state %#lx.\n", value);
1287 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1288 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1289 ok(!value, "Got unexpected alpha blend enable state %#lx.\n", value);
1290 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
1291 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1292 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1293 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1294 color = get_surface_color(rt, 320, 240);
1295 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1297 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1298 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1299 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1300 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1301 IDirect3D3_Release(d3d);
1303 if (ddraw_is_warp(ddraw))
1305 /* ddraw4 occasionally crashes in GetRenderTarget. */
1306 win_skip("Skipping test that crashes WARP occasionally.\n");
1307 goto done;
1310 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1311 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1312 hr = IDirectDrawSurface4_IsLost(rt);
1313 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
1315 memset(&lock, 0, sizeof(lock));
1316 lock.dwSize = sizeof(lock);
1317 lock.lpSurface = (void *)0xdeadbeef;
1318 hr = IDirectDrawSurface4_Lock(rt, NULL, &lock, DDLOCK_READONLY, NULL);
1319 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
1320 ok(lock.lpSurface == (void *)0xdeadbeef, "Got unexpected lock.lpSurface %p.\n", lock.lpSurface);
1322 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
1323 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1325 hr = IDirectDrawSurface4_Lock(rt, NULL, &lock, DDLOCK_READONLY, NULL);
1326 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1327 hr = IDirectDrawSurface4_Unlock(rt, NULL);
1328 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1330 hr = IDirect3DDevice3_GetRenderTarget(device, &surface);
1331 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1332 ok(surface == rt, "Got unexpected surface %p.\n", surface);
1333 IDirectDrawSurface4_Release(surface);
1334 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1335 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1336 ok(!!value, "Got unexpected z-enable state %#lx.\n", value);
1337 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1338 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1339 ok(!!value, "Got unexpected alpha blend enable state %#lx.\n", value);
1340 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ff00, 1.0f, 0);
1341 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1342 color = get_surface_color(rt, 320, 240);
1343 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1345 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1346 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1347 hr = IDirect3DDevice3_BeginScene(device);
1348 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1349 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
1350 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
1351 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1352 hr = IDirect3DDevice3_EndScene(device);
1353 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1354 color = get_surface_color(rt, 320, 240);
1355 ok(compare_color(color, 0x0000ff80, 1)
1356 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
1357 "Got unexpected color 0x%08x.\n", color);
1359 done:
1360 destroy_viewport(device, viewport);
1361 IDirectDrawSurface4_Release(rt);
1362 IDirect3DDevice3_Release(device);
1363 IDirectDraw4_Release(ddraw);
1364 DestroyWindow(window);
1367 static void test_surface_interface_mismatch(void)
1369 IDirectDraw4 *ddraw = NULL;
1370 IDirect3D3 *d3d = NULL;
1371 IDirectDrawSurface4 *surface = NULL, *ds;
1372 IDirectDrawSurface3 *surface3 = NULL;
1373 IDirect3DDevice3 *device = NULL;
1374 IDirect3DViewport3 *viewport = NULL;
1375 DDSURFACEDESC2 surface_desc;
1376 DDPIXELFORMAT z_fmt;
1377 unsigned int color;
1378 ULONG refcount;
1379 HRESULT hr;
1380 HWND window;
1381 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1383 window = create_window();
1384 ddraw = create_ddraw();
1385 ok(!!ddraw, "Failed to create a ddraw object.\n");
1386 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1387 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
1389 memset(&surface_desc, 0, sizeof(surface_desc));
1390 surface_desc.dwSize = sizeof(surface_desc);
1391 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1392 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1393 surface_desc.dwWidth = 640;
1394 surface_desc.dwHeight = 480;
1396 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1397 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
1399 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1400 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#lx.\n", hr);
1402 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
1404 skip("D3D interface is not available, skipping test.\n");
1405 goto cleanup;
1408 memset(&z_fmt, 0, sizeof(z_fmt));
1409 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
1410 if (FAILED(hr) || !z_fmt.dwSize)
1412 skip("No depth buffer formats available, skipping test.\n");
1413 goto cleanup;
1416 memset(&surface_desc, 0, sizeof(surface_desc));
1417 surface_desc.dwSize = sizeof(surface_desc);
1418 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
1419 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1420 U4(surface_desc).ddpfPixelFormat = z_fmt;
1421 surface_desc.dwWidth = 640;
1422 surface_desc.dwHeight = 480;
1423 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1424 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#lx.\n", hr);
1425 if (FAILED(hr))
1426 goto cleanup;
1428 /* Using a different surface interface version still works */
1429 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1430 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#lx.\n", hr);
1431 refcount = IDirectDrawSurface4_Release(ds);
1432 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
1433 if (FAILED(hr))
1434 goto cleanup;
1436 /* Here too */
1437 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface4 *)surface3, &device, NULL);
1438 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1439 if (FAILED(hr))
1440 goto cleanup;
1442 viewport = create_viewport(device, 0, 0, 640, 480);
1444 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1445 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
1446 color = get_surface_color(surface, 320, 240);
1447 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1449 cleanup:
1450 if (viewport)
1451 destroy_viewport(device, viewport);
1452 if (surface3) IDirectDrawSurface3_Release(surface3);
1453 if (surface) IDirectDrawSurface4_Release(surface);
1454 if (device) IDirect3DDevice3_Release(device);
1455 if (d3d) IDirect3D3_Release(d3d);
1456 if (ddraw) IDirectDraw4_Release(ddraw);
1457 DestroyWindow(window);
1460 static void test_coop_level_threaded(void)
1462 struct create_window_thread_param p;
1463 IDirectDraw4 *ddraw;
1464 HRESULT hr;
1466 ddraw = create_ddraw();
1467 ok(!!ddraw, "Failed to create a ddraw object.\n");
1468 create_window_thread(&p);
1470 hr = IDirectDraw4_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1471 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
1473 destroy_window_thread(&p);
1474 IDirectDraw4_Release(ddraw);
1477 static void test_depth_blit(const GUID *device_guid)
1479 static struct
1481 float x, y, z;
1482 DWORD color;
1484 quad1[] =
1486 { -1.0, 1.0, 0.50f, 0xff00ff00},
1487 { 1.0, 1.0, 0.50f, 0xff00ff00},
1488 { -1.0, -1.0, 0.50f, 0xff00ff00},
1489 { 1.0, -1.0, 0.50f, 0xff00ff00},
1491 static const unsigned int expected_colors[4][4] =
1493 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1494 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1495 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1496 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1498 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1500 IDirect3DDevice3 *device;
1501 IDirectDrawSurface4 *ds1, *ds2, *ds3, *rt;
1502 IDirect3DViewport3 *viewport;
1503 unsigned int color, i, j;
1504 RECT src_rect, dst_rect;
1505 HRESULT hr;
1506 IDirect3D3 *d3d;
1507 IDirectDraw4 *ddraw;
1508 DDBLTFX fx;
1509 HWND window;
1510 D3DRECT d3drect;
1512 window = create_window();
1513 if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid)))
1515 skip("Failed to create a 3D device, skipping test.\n");
1516 DestroyWindow(window);
1517 return;
1520 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1521 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1522 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1523 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1524 IDirect3D3_Release(d3d);
1526 ds1 = get_depth_stencil(device);
1528 memset(&ddsd_new, 0, sizeof(ddsd_new));
1529 ddsd_new.dwSize = sizeof(ddsd_new);
1530 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1531 ddsd_existing.dwSize = sizeof(ddsd_existing);
1532 hr = IDirectDrawSurface4_GetSurfaceDesc(ds1, &ddsd_existing);
1533 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1534 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1535 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1536 if (is_software_device_type(device_guid))
1537 ddsd_new.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
1538 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1539 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1540 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1541 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1542 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#lx.\n", hr);
1543 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1544 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#lx.\n", hr);
1545 IDirectDraw4_Release(ddraw);
1547 viewport = create_viewport(device, 0, 0, ddsd_existing.dwWidth, ddsd_existing.dwHeight);
1548 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1549 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#lx.\n", hr);
1551 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1552 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#lx.\n", hr);
1553 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1554 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#lx.\n", hr);
1556 U1(d3drect).x1 = U2(d3drect).y1 = 0;
1557 U3(d3drect).x2 = ddsd_existing.dwWidth; U4(d3drect).y2 = ddsd_existing.dwHeight;
1558 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1559 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#lx.\n", hr);
1561 /* Partial blit. */
1562 SetRect(&src_rect, 0, 0, 320, 240);
1563 SetRect(&dst_rect, 0, 0, 320, 240);
1564 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1565 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1566 /* Different locations. */
1567 SetRect(&src_rect, 0, 0, 320, 240);
1568 SetRect(&dst_rect, 320, 240, 640, 480);
1569 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1570 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1571 /* Stretched. */
1572 SetRect(&src_rect, 0, 0, 320, 240);
1573 SetRect(&dst_rect, 0, 0, 640, 480);
1574 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1575 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1576 /* Flipped. */
1577 SetRect(&src_rect, 0, 480, 640, 0);
1578 SetRect(&dst_rect, 0, 0, 640, 480);
1579 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1580 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
1581 SetRect(&src_rect, 0, 0, 640, 480);
1582 SetRect(&dst_rect, 0, 480, 640, 0);
1583 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1584 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
1585 /* Full, explicit. */
1586 SetRect(&src_rect, 0, 0, 640, 480);
1587 SetRect(&dst_rect, 0, 0, 640, 480);
1588 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1589 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1590 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1592 /* Depth blit inside a BeginScene / EndScene pair */
1593 hr = IDirect3DDevice3_BeginScene(device);
1594 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#lx.\n", hr);
1595 /* From the current depth stencil */
1596 hr = IDirectDrawSurface4_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1597 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1598 /* To the current depth stencil */
1599 hr = IDirectDrawSurface4_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1600 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1601 /* Between unbound surfaces */
1602 hr = IDirectDrawSurface4_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1603 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1604 hr = IDirect3DDevice3_EndScene(device);
1605 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#lx.\n", hr);
1607 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1608 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1609 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1610 * a reliable result(z = 0.0) */
1611 memset(&fx, 0, sizeof(fx));
1612 fx.dwSize = sizeof(fx);
1613 hr = IDirectDrawSurface4_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1614 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1616 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1617 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1619 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1620 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1622 color = get_surface_color(rt, 80, 60);
1623 /* For some reason clears and colour fill blits randomly fail with software render target. */
1624 ok(color == 0x00ff0000 || broken(is_software_device_type(device_guid) && !color),
1625 "Got unexpected colour 0x%08x.\n", color);
1626 if (!color)
1628 fill_surface(rt, 0xffff0000);
1630 color = get_surface_color(rt, 80, 60);
1631 ok(color == 0x00ff0000, "Got unexpected colour 0x%08x.\n", color);
1634 SetRect(&dst_rect, 0, 0, 320, 240);
1635 hr = IDirectDrawSurface4_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1636 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1637 IDirectDrawSurface4_Release(ds3);
1638 IDirectDrawSurface4_Release(ds2);
1639 IDirectDrawSurface4_Release(ds1);
1641 hr = IDirect3DDevice3_BeginScene(device);
1642 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1643 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1644 quad1, 4, 0);
1645 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1646 hr = IDirect3DDevice3_EndScene(device);
1647 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1649 for (i = 0; i < 4; ++i)
1651 for (j = 0; j < 4; ++j)
1653 unsigned int x = 80 * ((2 * j) + 1);
1654 unsigned int y = 60 * ((2 * i) + 1);
1655 color = get_surface_color(rt, x, y);
1656 ok(compare_color(color, expected_colors[i][j], 1),
1657 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1660 IDirectDrawSurface4_Release(rt);
1662 destroy_viewport(device, viewport);
1663 IDirect3DDevice3_Release(device);
1664 DestroyWindow(window);
1667 static void test_texture_load_ckey(void)
1669 IDirectDraw4 *ddraw;
1670 IDirectDrawSurface4 *src;
1671 IDirectDrawSurface4 *dst;
1672 IDirect3DTexture2 *src_tex;
1673 IDirect3DTexture2 *dst_tex;
1674 DDSURFACEDESC2 ddsd;
1675 HRESULT hr;
1676 DDCOLORKEY ckey;
1678 ddraw = create_ddraw();
1679 ok(!!ddraw, "Failed to create a ddraw object.\n");
1680 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1681 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
1683 memset(&ddsd, 0, sizeof(ddsd));
1684 ddsd.dwSize = sizeof(ddsd);
1685 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1686 ddsd.dwHeight = 128;
1687 ddsd.dwWidth = 128;
1688 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1689 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &src, NULL);
1690 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#lx.\n", hr);
1691 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1692 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &dst, NULL);
1693 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#lx.\n", hr);
1695 hr = IDirectDrawSurface4_QueryInterface(src, &IID_IDirect3DTexture2, (void **)&src_tex);
1696 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture2 interface, hr %#lx.\n", hr);
1697 if (FAILED(hr))
1699 /* 64 bit ddraw does not support d3d */
1700 skip("Could not get Direct3DTexture2 interface, skipping texture::Load color keying tests.\n");
1701 IDirectDrawSurface4_Release(dst);
1702 IDirectDrawSurface4_Release(src);
1703 IDirectDraw4_Release(ddraw);
1704 return;
1706 hr = IDirectDrawSurface4_QueryInterface(dst, &IID_IDirect3DTexture2, (void **)&dst_tex);
1707 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture2 interface, hr %#lx.\n", hr);
1709 /* No surface has a color key */
1710 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1711 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1712 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1713 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1714 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx.\n", hr);
1715 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
1716 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
1718 /* Source surface has a color key */
1719 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1720 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1721 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
1722 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1723 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1724 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1725 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1726 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
1727 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
1729 /* Both surfaces have a color key: Dest ckey is overwritten */
1730 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1731 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1732 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
1733 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1734 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1735 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1736 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1737 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
1738 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
1740 /* Only the destination has a color key: It is not deleted */
1741 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1742 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
1743 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1744 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx.\n", hr);
1745 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1746 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1747 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1748 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1749 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
1750 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
1752 IDirect3DTexture2_Release(dst_tex);
1753 IDirect3DTexture2_Release(src_tex);
1754 IDirectDrawSurface4_Release(dst);
1755 IDirectDrawSurface4_Release(src);
1756 IDirectDraw4_Release(ddraw);
1759 static BOOL compare_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
1761 return mode1->dmPosition.x == mode2->dmPosition.x
1762 && mode1->dmPosition.y == mode2->dmPosition.y
1763 && mode1->dmPelsWidth == mode2->dmPelsWidth
1764 && mode1->dmPelsHeight == mode2->dmPelsHeight;
1767 static ULONG get_refcount(IUnknown *test_iface)
1769 IUnknown_AddRef(test_iface);
1770 return IUnknown_Release(test_iface);
1773 static void test_viewport_object(void)
1775 IDirect3DViewport3 *viewport3, *another_vp, *test_vp;
1776 IDirectDrawGammaControl *gamma;
1777 IDirect3DViewport2 *viewport2;
1778 IDirect3DViewport *viewport;
1779 IDirect3DDevice3 *device;
1780 HRESULT hr, old_d3d_ref;
1781 IDirectDraw4 *ddraw;
1782 IUnknown *unknown;
1783 D3DVIEWPORT2 vp2;
1784 IDirect3D3 *d3d;
1785 D3DVIEWPORT vp;
1786 HWND window;
1787 ULONG ref;
1788 union
1790 D3DVIEWPORT2 vp2;
1791 D3DVIEWPORT vp1;
1792 BYTE blob[1024];
1793 } desc;
1795 window = create_window();
1796 if (!(device = create_device(window, DDSCL_NORMAL)))
1798 skip("Failed to create a 3D device, skipping test.\n");
1799 DestroyWindow(window);
1800 return;
1802 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1803 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1804 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1805 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1806 old_d3d_ref = get_refcount((IUnknown *) d3d);
1808 hr = IDirect3D3_CreateViewport(d3d, &viewport3, NULL);
1809 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1810 ref = get_refcount((IUnknown *)viewport3);
1811 ok(ref == 1, "Got unexpected refcount %lu.\n", ref);
1812 ref = get_refcount((IUnknown *)d3d);
1813 ok(ref == old_d3d_ref, "Got unexpected refcount %lu.\n", ref);
1815 memset(&desc, 0, sizeof(desc));
1816 hr = IDirect3DViewport3_GetViewport(viewport3, &desc.vp1);
1817 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1818 desc.vp1.dwSize = sizeof(desc.vp1) + 1;
1819 hr = IDirect3DViewport3_GetViewport(viewport3, &desc.vp1);
1820 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1821 desc.vp1.dwSize = sizeof(desc.vp1) - 1;
1822 hr = IDirect3DViewport3_GetViewport(viewport3, &desc.vp1);
1823 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1824 desc.vp1.dwSize = sizeof(desc.vp1);
1825 hr = IDirect3DViewport3_GetViewport(viewport3, &desc.vp1);
1826 ok(hr == D3DERR_VIEWPORTDATANOTSET, "Got unexpected hr %#lx.\n", hr);
1827 ok(desc.vp1.dwSize == sizeof(desc.vp1), "Got unexpected dwSize %lu.\n", desc.vp1.dwSize);
1828 hr = IDirect3DViewport3_GetViewport2(viewport3, &desc.vp2);
1829 ok(hr == D3DERR_VIEWPORTDATANOTSET, "Got unexpected hr %#lx.\n", hr);
1830 ok(desc.vp2.dwSize == sizeof(desc.vp2), "Got unexpected dwSize %lu.\n", desc.vp2.dwSize);
1831 desc.vp2.dwSize = sizeof(desc.vp2) + 1;
1832 hr = IDirect3DViewport3_GetViewport2(viewport3, &desc.vp2);
1833 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1835 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1836 hr = IDirect3DViewport2_QueryInterface(viewport3, &IID_IDirectDrawGammaControl, (void **)&gamma);
1837 ok(hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr);
1838 ok(!gamma, "Interface not set to NULL by failed QI call: %p.\n", gamma);
1839 /* NULL iid: Segfaults */
1841 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport, (void **)&viewport);
1842 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1843 ref = get_refcount((IUnknown *)viewport);
1844 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1845 ref = get_refcount((IUnknown *)viewport3);
1846 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1847 IDirect3DViewport_Release(viewport);
1848 viewport = NULL;
1850 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport3, (void **)&viewport2);
1851 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1852 ref = get_refcount((IUnknown *)viewport2);
1853 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1854 ref = get_refcount((IUnknown *)viewport3);
1855 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1856 IDirect3DViewport3_Release(viewport2);
1858 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IUnknown, (void **)&unknown);
1859 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1860 ref = get_refcount((IUnknown *)viewport3);
1861 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1862 ref = get_refcount(unknown);
1863 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1864 IUnknown_Release(unknown);
1866 hr = IDirect3DDevice3_DeleteViewport(device, NULL);
1867 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1868 hr = IDirect3DDevice3_GetCurrentViewport(device, NULL);
1869 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#lx.\n", hr);
1871 hr = IDirect3D3_CreateViewport(d3d, &another_vp, NULL);
1872 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1874 /* Setting a viewport not in the viewport list fails */
1875 hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
1876 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1878 /* AddViewport(NULL): Segfault */
1879 hr = IDirect3DDevice3_AddViewport(device, viewport3);
1880 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1881 ref = get_refcount((IUnknown *) viewport3);
1882 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1883 hr = IDirect3DDevice3_AddViewport(device, another_vp);
1884 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1885 ref = get_refcount((IUnknown *) another_vp);
1886 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1888 test_vp = (IDirect3DViewport3 *) 0xbaadc0de;
1889 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1890 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#lx.\n", hr);
1891 ok(test_vp == (IDirect3DViewport3 *) 0xbaadc0de, "Got unexpected pointer %p.\n", test_vp);
1893 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
1894 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1895 ref = get_refcount((IUnknown *) viewport3);
1896 ok(ref == 3, "Got unexpected refcount %lu.\n", ref);
1897 ref = get_refcount((IUnknown *) device);
1898 ok(ref == 1, "Got unexpected refcount %lu.\n", ref);
1900 test_vp = NULL;
1901 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1902 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1903 ok(test_vp == viewport3, "Got unexpected viewport %p.\n", test_vp);
1904 ref = get_refcount((IUnknown *) viewport3);
1905 ok(ref == 4, "Got unexpected refcount %lu.\n", ref);
1906 if (test_vp)
1907 IDirect3DViewport3_Release(test_vp);
1909 /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
1911 /* Cannot set the viewport to NULL */
1912 hr = IDirect3DDevice3_SetCurrentViewport(device, NULL);
1913 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1914 test_vp = NULL;
1915 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1916 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1917 ok(test_vp == viewport3, "Got unexpected viewport %p.\n", test_vp);
1918 if (test_vp)
1919 IDirect3DViewport3_Release(test_vp);
1921 /* SetCurrentViewport properly releases the old viewport's reference */
1922 hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
1923 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1924 ref = get_refcount((IUnknown *) viewport3);
1925 ok(ref == 2, "Got unexpected refcount %lu.\n", ref);
1926 ref = get_refcount((IUnknown *) another_vp);
1927 ok(ref == 3, "Got unexpected refcount %lu.\n", ref);
1929 /* Unlike device2::DeleteViewport, device3::DeleteViewport releases the
1930 * reference held by SetCurrentViewport */
1931 hr = IDirect3DDevice3_DeleteViewport(device, another_vp);
1932 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1933 ref = get_refcount((IUnknown *) another_vp);
1934 ok(ref == 1, "Got unexpected refcount %lu.\n", ref);
1936 /* GetCurrentViewport still fails */
1937 test_vp = NULL;
1938 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1939 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#lx.\n", hr);
1940 ok(!test_vp, "Got unexpected viewport %p.\n", test_vp);
1942 /* Setting a different viewport doesn't have any surprises now */
1943 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
1944 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1945 ref = get_refcount((IUnknown *) viewport3);
1946 ok(ref == 3, "Got unexpected refcount %lu.\n", ref);
1947 ref = get_refcount((IUnknown *) another_vp);
1948 ok(ref == 1, "Got unexpected refcount %lu.\n", ref);
1950 memset(&vp, 0, sizeof(vp));
1951 memset(&vp, 0, sizeof(vp2));
1952 vp.dwSize = vp2.dwSize = 0;
1953 vp.dwX = vp2.dwX = 0;
1954 vp.dwY = vp2.dwY = 0;
1955 vp.dwWidth = vp2.dwWidth = 640;
1956 vp.dwHeight = vp2.dwHeight = 480;
1957 vp.dvMinZ = vp2.dvMinZ = 0.0f;
1958 vp.dvMaxZ = vp2.dvMaxZ = 1.0f;
1959 vp.dvScaleX = vp.dwWidth / 2.0f;
1960 vp.dvScaleY = vp.dwHeight / 2.0f;
1961 vp.dvMaxX = 1.0f;
1962 vp.dvMaxY = 1.0f;
1963 vp2.dvClipX = -1.0f;
1964 vp2.dvClipY = 1.0f;
1965 vp2.dvClipWidth = 2.0f;
1966 vp2.dvClipHeight = 2.0f;
1967 hr = IDirect3DViewport3_SetViewport(viewport3, &vp);
1968 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1969 hr = IDirect3DViewport3_SetViewport2(viewport3, &vp2);
1970 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
1972 vp.dwSize = sizeof(vp);
1973 hr = IDirect3DViewport3_SetViewport(viewport3, &vp);
1974 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1975 vp2.dwSize = sizeof(vp2);
1976 hr = IDirect3DViewport3_SetViewport2(viewport3, &vp2);
1977 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1979 vp2.dwSize = sizeof(vp2);
1980 vp2.dwX = 160;
1981 vp2.dwY = 120;
1982 vp2.dwWidth = 640 - vp2.dwX;
1983 vp2.dwHeight = 480 - vp2.dwY;
1984 vp2.dvClipX = 2.0f;
1985 vp2.dvClipY = -1.75f;
1986 vp2.dvClipWidth = 2.5f;
1987 vp2.dvClipHeight = -1.5f;
1988 vp2.dvMinZ = 0.5f;
1989 vp2.dvMaxZ = 2.0f;
1990 hr = IDirect3DViewport3_SetViewport2(viewport3, &vp2);
1991 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1993 memset(&vp, 0xff, sizeof(vp));
1994 vp.dwSize = sizeof(vp);
1995 hr = IDirect3DViewport3_GetViewport(viewport3, &vp);
1996 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
1997 ok(vp.dvMaxX == 4.5f && vp.dvMaxY == -1.75f && vp.dvScaleX == 192.0f
1998 && vp.dvScaleY == -240.0f && vp.dvMinZ == 0.0f && vp.dvMaxZ == 1.0f,
1999 "Got unexpected values %g, %g, %g, %g, %g, %g.\n",
2000 vp.dvMaxX, vp.dvMaxY, vp.dvScaleX, vp.dvScaleY, vp.dvMinZ, vp.dvMaxZ);
2002 vp2.dvClipX = -1.5f;
2003 vp2.dvClipY = 1.75f;
2004 vp2.dvClipWidth = -1.5f;
2005 vp2.dvClipHeight = 2.0f;
2006 vp2.dvMinZ = 2.0f;
2007 vp2.dvMaxZ = 0.5f;
2009 hr = IDirect3DViewport3_SetViewport2(viewport3, &vp2);
2010 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
2012 memset(&vp, 0xff, sizeof(vp));
2013 vp.dwSize = sizeof(vp);
2014 hr = IDirect3DViewport3_GetViewport(viewport3, &vp);
2015 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
2016 ok(vp.dvMaxX == -3.0f && vp.dvMaxY == 1.75f && vp.dvScaleX == -320.0f
2017 && vp.dvScaleY == 180.0f && vp.dvMinZ == 0.0f && vp.dvMaxZ == 1.0f,
2018 "Got unexpected values %g, %g, %g, %g, %g, %g.\n",
2019 vp.dvMaxX, vp.dvMaxY, vp.dvScaleX, vp.dvScaleY, vp.dvMinZ, vp.dvMaxZ);
2021 vp.dwSize = sizeof(vp);
2022 vp.dvMinZ = 0.5f;
2023 vp.dvMaxZ = 2.0f;
2024 hr = IDirect3DViewport3_SetViewport(viewport3, &vp);
2025 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
2027 memset(&vp2, 0xff, sizeof(vp2));
2028 vp2.dwSize = sizeof(vp2);
2029 hr = IDirect3DViewport3_GetViewport2(viewport3, &vp2);
2030 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
2031 ok(vp2.dvClipX == 0.75f && vp2.dvClipY == 1.0f && vp2.dvClipWidth == -1.5f
2032 && vp2.dvClipHeight == 2.0f && vp2.dvMinZ == 0.0f && vp2.dvMaxZ == 1.0f,
2033 "Got unexpected values %g, %g, %g, %g, %g, %g.\n",
2034 vp2.dvClipX, vp2.dvClipY, vp2.dvClipWidth, vp2.dvClipHeight, vp2.dvMinZ, vp2.dvMaxZ);
2036 vp.dvMaxX = 4.5f;
2037 vp.dvMaxY = -1.75f;
2038 vp.dvScaleX = 192.0f;
2039 vp.dvScaleY = -240.0f;
2040 vp.dvMinZ = 2.0f;
2041 vp.dvMaxZ = 0.5f;
2043 hr = IDirect3DViewport3_SetViewport(viewport3, &vp);
2044 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
2046 memset(&vp2, 0xff, sizeof(vp2));
2047 vp2.dwSize = sizeof(vp2);
2048 hr = IDirect3DViewport3_GetViewport2(viewport3, &vp2);
2049 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
2050 ok(vp2.dvClipX == -1.25f && vp2.dvClipY == -0.75f && vp2.dvClipWidth == 2.5f
2051 && vp2.dvClipHeight == -1.5f && vp2.dvMinZ == 0.0f && vp2.dvMaxZ == 1.0f,
2052 "Got unexpected values %g, %g, %g, %g, %g, %g.\n",
2053 vp2.dvClipX, vp2.dvClipY, vp2.dvClipWidth, vp2.dvClipHeight, vp2.dvMinZ, vp2.dvMaxZ);
2055 /* Destroying the device removes the viewport and releases the reference */
2056 IDirect3DDevice3_Release(device);
2057 ref = get_refcount((IUnknown *) viewport3);
2058 ok(ref == 1, "Got unexpected refcount %lu.\n", ref);
2060 memset(&vp2, 0xff, sizeof(vp2));
2061 vp2.dwSize = sizeof(vp2);
2062 hr = IDirect3DViewport3_GetViewport2(viewport3, &vp2);
2063 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
2064 ok(vp2.dvClipX == -1.25f && vp2.dvClipY == -0.75f && vp2.dvClipWidth == 2.5f
2065 && vp2.dvClipHeight == -1.5f && vp2.dvMinZ == 0.0f && vp2.dvMaxZ == 1.0f,
2066 "Got unexpected values %g, %g, %g, %g, %g, %g.\n",
2067 vp2.dvClipX, vp2.dvClipY, vp2.dvClipWidth, vp2.dvClipHeight, vp2.dvMinZ, vp2.dvMaxZ);
2069 vp.dwSize = sizeof(vp);
2070 hr = IDirect3DViewport3_SetViewport(viewport3, &vp);
2071 ok(hr == D3DERR_VIEWPORTHASNODEVICE, "Got unexpected hr %#lx.\n", hr);
2072 vp2.dwSize = sizeof(vp2);
2073 hr = IDirect3DViewport3_SetViewport2(viewport3, &vp2);
2074 ok(hr == D3DERR_VIEWPORTHASNODEVICE, "Got unexpected hr %#lx.\n", hr);
2076 ref = IDirect3DViewport3_Release(another_vp);
2077 ok(!ref, "Got unexpected refcount %lu.\n", ref);
2078 ref = IDirect3DViewport3_Release(viewport3);
2079 ok(!ref, "Got unexpected refcount %lu.\n", ref);
2080 IDirect3D3_Release(d3d);
2081 DestroyWindow(window);
2082 IDirectDraw4_Release(ddraw);
2085 static void test_zenable(const GUID *device_guid)
2087 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
2088 static struct
2090 struct vec4 position;
2091 D3DCOLOR diffuse;
2093 tquad[] =
2095 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
2096 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xff00ff00},
2097 {{640.0f, 480.0f, 1.5f, 1.0f}, 0xff00ff00},
2098 {{640.0f, 0.0f, 1.5f, 1.0f}, 0xff00ff00},
2100 unsigned int color, x, y, i, j;
2101 IDirect3DViewport3 *viewport;
2102 IDirect3DDevice3 *device;
2103 IDirectDrawSurface4 *rt;
2104 HWND window;
2105 HRESULT hr;
2107 window = create_window();
2108 if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid)))
2110 skip("Failed to create a 3D device, skipping test.\n");
2111 DestroyWindow(window);
2112 return;
2115 viewport = create_viewport(device, 0, 0, 640, 480);
2116 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
2117 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2119 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
2120 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2122 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
2123 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2125 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
2126 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2128 color = get_surface_color(rt, 80, 60);
2129 /* For some reason clears and colour fill blits randomly fail with software render target. */
2130 ok(color == 0x00ff0000 || broken(is_software_device_type(device_guid) && !color),
2131 "Got unexpected colour 0x%08x.\n", color);
2132 if (!color)
2134 fill_surface(rt, 0xffff0000);
2136 color = get_surface_color(rt, 80, 60);
2137 ok(color == 0x00ff0000, "Got unexpected colour 0x%08x.\n", color);
2140 hr = IDirect3DDevice3_BeginScene(device);
2141 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2142 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
2143 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2144 hr = IDirect3DDevice3_EndScene(device);
2145 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2147 for (i = 0; i < 4; ++i)
2149 for (j = 0; j < 4; ++j)
2151 x = 80 * ((2 * j) + 1);
2152 y = 60 * ((2 * i) + 1);
2153 color = get_surface_color(rt, x, y);
2154 ok(compare_color(color, 0x0000ff00, 1),
2155 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
2158 IDirectDrawSurface4_Release(rt);
2160 destroy_viewport(device, viewport);
2161 IDirect3DDevice3_Release(device);
2162 DestroyWindow(window);
2165 static void test_ck_rgba(const GUID *device_guid)
2167 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
2168 static struct
2170 struct vec4 position;
2171 struct vec2 texcoord;
2173 tquad[] =
2175 {{ 0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
2176 {{ 0.0f, 0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
2177 {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
2178 {{640.0f, 0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
2179 {{ 0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
2180 {{ 0.0f, 0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
2181 {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
2182 {{640.0f, 0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
2184 static const struct
2186 D3DCOLOR fill_color;
2187 BOOL color_key;
2188 BOOL blend;
2189 unsigned int result1, result1_broken;
2190 unsigned int result2, result2_broken;
2192 tests[] =
2194 /* r200 on Windows doesn't check the alpha component when applying the color
2195 * key, so the key matches on every texel. */
2196 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
2197 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
2198 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
2199 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
2200 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
2201 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
2202 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
2203 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
2206 IDirectDrawSurface4 *surface;
2207 IDirect3DViewport3 *viewport;
2208 DDSURFACEDESC2 surface_desc;
2209 IDirect3DTexture2 *texture;
2210 IDirect3DDevice3 *device;
2211 IDirectDrawSurface4 *rt;
2212 unsigned int color, i;
2213 IDirectDraw4 *ddraw;
2214 IDirect3D3 *d3d;
2215 HWND window;
2216 DDBLTFX fx;
2217 HRESULT hr;
2219 window = create_window();
2220 if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid)))
2222 skip("Failed to create a 3D device, skipping test.\n");
2223 DestroyWindow(window);
2224 return;
2227 viewport = create_viewport(device, 0, 0, 640, 480);
2228 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
2229 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2231 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
2232 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2233 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
2234 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2235 IDirect3D3_Release(d3d);
2237 memset(&surface_desc, 0, sizeof(surface_desc));
2238 surface_desc.dwSize = sizeof(surface_desc);
2239 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
2240 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2241 if (is_software_device_type(device_guid))
2242 surface_desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
2243 surface_desc.dwWidth = 256;
2244 surface_desc.dwHeight = 256;
2245 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
2246 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
2247 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
2248 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
2249 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
2250 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
2251 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
2252 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
2253 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
2254 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2255 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
2256 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
2257 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
2259 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
2260 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2261 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
2262 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2263 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
2264 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2266 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
2267 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2269 for (i = 0; i < ARRAY_SIZE(tests); ++i)
2271 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
2272 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2273 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
2274 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2276 memset(&fx, 0, sizeof(fx));
2277 fx.dwSize = sizeof(fx);
2278 U5(fx).dwFillColor = tests[i].fill_color;
2279 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
2280 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
2282 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
2283 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
2284 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2285 if (is_software_device_type(device_guid))
2286 fill_surface(rt, 0xffff0000);
2287 hr = IDirect3DDevice3_BeginScene(device);
2288 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2289 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
2290 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2291 hr = IDirect3DDevice3_EndScene(device);
2292 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2294 color = get_surface_color(rt, 320, 240);
2295 ok(compare_color(color, tests[i].result1, 2) || compare_color(color, tests[i].result1_broken, 1),
2296 "Expected color 0x%08x for test %u, got 0x%08x.\n",
2297 tests[i].result1, i, color);
2299 U5(fx).dwFillColor = 0xff0000ff;
2300 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
2301 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
2303 hr = IDirect3DDevice3_BeginScene(device);
2304 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2305 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
2306 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2307 hr = IDirect3DDevice3_EndScene(device);
2308 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2310 /* This tests that fragments that are masked out by the color key are
2311 * discarded, instead of just fully transparent. */
2312 color = get_surface_color(rt, 320, 240);
2313 ok(compare_color(color, tests[i].result2, 2) || compare_color(color, tests[i].result2_broken, 1),
2314 "Expected color 0x%08x for test %u, got 0x%08x.\n",
2315 tests[i].result2, i, color);
2318 IDirectDrawSurface4_Release(rt);
2319 IDirect3DTexture2_Release(texture);
2320 IDirectDrawSurface4_Release(surface);
2321 destroy_viewport(device, viewport);
2322 IDirectDraw4_Release(ddraw);
2323 IDirect3DDevice3_Release(device);
2324 DestroyWindow(window);
2327 static void test_ck_default(void)
2329 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
2330 static struct
2332 struct vec4 position;
2333 struct vec2 texcoord;
2335 tquad[] =
2337 {{ 0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
2338 {{ 0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
2339 {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
2340 {{640.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
2342 IDirectDrawSurface4 *surface, *rt;
2343 IDirect3DViewport3 *viewport;
2344 DDSURFACEDESC2 surface_desc;
2345 IDirect3DTexture2 *texture;
2346 IDirect3DDevice3 *device;
2347 IDirectDraw4 *ddraw;
2348 unsigned int color;
2349 IDirect3D3 *d3d;
2350 DWORD value;
2351 HWND window;
2352 DDBLTFX fx;
2353 HRESULT hr;
2355 window = create_window();
2356 if (!(device = create_device(window, DDSCL_NORMAL)))
2358 skip("Failed to create a 3D device, skipping test.\n");
2359 DestroyWindow(window);
2360 return;
2363 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
2364 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
2365 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
2366 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#lx.\n", hr);
2367 IDirect3D3_Release(d3d);
2369 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
2370 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
2372 viewport = create_viewport(device, 0, 0, 640, 480);
2373 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
2374 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
2376 memset(&surface_desc, 0, sizeof(surface_desc));
2377 surface_desc.dwSize = sizeof(surface_desc);
2378 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
2379 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2380 surface_desc.dwWidth = 256;
2381 surface_desc.dwHeight = 256;
2382 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
2383 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
2384 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
2385 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
2386 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
2387 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
2388 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
2389 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
2390 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2391 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
2392 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
2393 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
2394 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
2395 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
2397 memset(&fx, 0, sizeof(fx));
2398 fx.dwSize = sizeof(fx);
2399 U5(fx).dwFillColor = 0x000000ff;
2400 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
2401 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#lx.\n", hr);
2403 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
2404 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
2405 hr = IDirect3DDevice3_BeginScene(device);
2406 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
2407 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
2408 ok(SUCCEEDED(hr), "Failed to get render state, hr %#lx.\n", hr);
2409 ok(!value, "Got unexpected color keying state %#lx.\n", value);
2410 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
2411 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
2412 hr = IDirect3DDevice3_EndScene(device);
2413 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
2414 color = get_surface_color(rt, 320, 240);
2415 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
2417 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
2418 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
2419 hr = IDirect3DDevice3_BeginScene(device);
2420 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
2421 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
2422 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#lx.\n", hr);
2423 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
2424 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
2425 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
2426 ok(SUCCEEDED(hr), "Failed to get render state, hr %#lx.\n", hr);
2427 ok(!!value, "Got unexpected color keying state %#lx.\n", value);
2428 hr = IDirect3DDevice3_EndScene(device);
2429 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
2430 color = get_surface_color(rt, 320, 240);
2431 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
2433 IDirect3DTexture_Release(texture);
2434 IDirectDrawSurface4_Release(surface);
2435 destroy_viewport(device, viewport);
2436 IDirectDrawSurface4_Release(rt);
2437 IDirect3DDevice3_Release(device);
2438 IDirectDraw4_Release(ddraw);
2439 DestroyWindow(window);
2442 static void test_ck_complex(void)
2444 IDirectDrawSurface4 *surface, *mipmap, *tmp;
2445 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
2446 DDSURFACEDESC2 surface_desc;
2447 IDirect3DDevice3 *device;
2448 DDCOLORKEY color_key;
2449 IDirectDraw4 *ddraw;
2450 IDirect3D3 *d3d;
2451 unsigned int i;
2452 ULONG refcount;
2453 HWND window;
2454 HRESULT hr;
2456 window = create_window();
2457 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
2459 skip("Failed to create a 3D device, skipping test.\n");
2460 DestroyWindow(window);
2461 return;
2463 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
2464 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
2465 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
2466 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#lx.\n", hr);
2467 IDirect3D3_Release(d3d);
2469 memset(&surface_desc, 0, sizeof(surface_desc));
2470 surface_desc.dwSize = sizeof(surface_desc);
2471 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2472 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2473 surface_desc.dwWidth = 128;
2474 surface_desc.dwHeight = 128;
2475 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2476 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
2478 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2479 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx.\n", hr);
2480 color_key.dwColorSpaceLowValue = 0x0000ff00;
2481 color_key.dwColorSpaceHighValue = 0x0000ff00;
2482 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2483 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
2484 memset(&color_key, 0, sizeof(color_key));
2485 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2486 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
2487 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2488 color_key.dwColorSpaceLowValue);
2489 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2490 color_key.dwColorSpaceHighValue);
2492 mipmap = surface;
2493 IDirectDrawSurface_AddRef(mipmap);
2494 for (i = 0; i < 7; ++i)
2496 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
2497 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#lx.\n", i, hr);
2499 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2500 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx, i %u.\n", hr, i);
2501 color_key.dwColorSpaceLowValue = 0x000000ff;
2502 color_key.dwColorSpaceHighValue = 0x000000ff;
2503 hr = IDirectDrawSurface4_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2504 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx, i %u.\n", hr, i);
2505 memset(&color_key, 0, sizeof(color_key));
2506 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2507 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx, i %u.\n", hr, i);
2508 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08lx, i %u.\n",
2509 color_key.dwColorSpaceLowValue, i);
2510 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08lx, i %u.\n",
2511 color_key.dwColorSpaceHighValue, i);
2513 IDirectDrawSurface_Release(mipmap);
2514 mipmap = tmp;
2517 memset(&color_key, 0, sizeof(color_key));
2518 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2519 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
2520 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2521 color_key.dwColorSpaceLowValue);
2522 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2523 color_key.dwColorSpaceHighValue);
2525 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
2526 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
2527 IDirectDrawSurface_Release(mipmap);
2528 refcount = IDirectDrawSurface4_Release(surface);
2529 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
2531 memset(&surface_desc, 0, sizeof(surface_desc));
2532 surface_desc.dwSize = sizeof(surface_desc);
2533 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
2534 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
2535 U5(surface_desc).dwBackBufferCount = 1;
2536 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2537 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
2539 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2540 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx.\n", hr);
2541 color_key.dwColorSpaceLowValue = 0x0000ff00;
2542 color_key.dwColorSpaceHighValue = 0x0000ff00;
2543 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2544 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
2545 memset(&color_key, 0, sizeof(color_key));
2546 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2547 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
2548 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2549 color_key.dwColorSpaceLowValue);
2550 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2551 color_key.dwColorSpaceHighValue);
2553 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &tmp);
2554 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#lx.\n", hr);
2556 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2557 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#lx, i %u.\n", hr, i);
2558 color_key.dwColorSpaceLowValue = 0x0000ff00;
2559 color_key.dwColorSpaceHighValue = 0x0000ff00;
2560 hr = IDirectDrawSurface4_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2561 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
2562 memset(&color_key, 0, sizeof(color_key));
2563 hr = IDirectDrawSurface4_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2564 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
2565 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2566 color_key.dwColorSpaceLowValue);
2567 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08lx.\n",
2568 color_key.dwColorSpaceHighValue);
2570 IDirectDrawSurface_Release(tmp);
2572 refcount = IDirectDrawSurface4_Release(surface);
2573 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
2574 IDirectDraw4_Release(ddraw);
2575 refcount = IDirect3DDevice3_Release(device);
2576 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
2577 DestroyWindow(window);
2580 struct qi_test
2582 REFIID iid;
2583 REFIID refcount_iid;
2584 HRESULT hr;
2587 static void test_qi(const char *test_name, IUnknown *base_iface,
2588 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
2590 ULONG refcount, expected_refcount;
2591 IUnknown *iface1, *iface2;
2592 HRESULT hr;
2593 UINT i, j;
2595 for (i = 0; i < entry_count; ++i)
2597 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
2598 ok(hr == tests[i].hr, "Got hr %#lx for test \"%s\" %u.\n", hr, test_name, i);
2599 if (SUCCEEDED(hr))
2601 for (j = 0; j < entry_count; ++j)
2603 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
2604 ok(hr == tests[j].hr, "Got hr %#lx for test \"%s\" %u, %u.\n", hr, test_name, i, j);
2605 if (SUCCEEDED(hr))
2607 expected_refcount = 0;
2608 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
2609 ++expected_refcount;
2610 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
2611 ++expected_refcount;
2612 refcount = IUnknown_Release(iface2);
2613 ok(refcount == expected_refcount, "Got refcount %lu for test \"%s\" %u, %u, expected %lu.\n",
2614 refcount, test_name, i, j, expected_refcount);
2618 expected_refcount = 0;
2619 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
2620 ++expected_refcount;
2621 refcount = IUnknown_Release(iface1);
2622 ok(refcount == expected_refcount, "Got refcount %lu for test \"%s\" %u, expected %lu.\n",
2623 refcount, test_name, i, expected_refcount);
2628 static void test_surface_qi(void)
2630 static const struct qi_test tests[] =
2632 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface4, S_OK },
2633 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface4, S_OK },
2634 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
2635 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2636 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
2637 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
2638 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
2639 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
2640 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
2641 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
2642 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
2643 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
2644 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
2645 {&IID_IDirect3D7, NULL, E_INVALIDARG },
2646 {&IID_IDirect3D3, NULL, E_INVALIDARG },
2647 {&IID_IDirect3D2, NULL, E_INVALIDARG },
2648 {&IID_IDirect3D, NULL, E_INVALIDARG },
2649 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
2650 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
2651 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
2652 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
2653 {&IID_IDirectDraw, NULL, E_INVALIDARG },
2654 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
2655 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
2656 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
2657 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
2658 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
2659 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
2660 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
2661 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
2662 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
2663 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
2664 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
2665 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
2666 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
2667 {NULL, NULL, E_INVALIDARG },
2670 IDirectDrawSurface4 *surface;
2671 DDSURFACEDESC2 surface_desc;
2672 IDirect3DDevice3 *device;
2673 IDirectDraw4 *ddraw;
2674 HWND window;
2675 HRESULT hr;
2677 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
2679 win_skip("DirectDrawCreateEx not available, skipping test.\n");
2680 return;
2683 window = create_window();
2684 /* Try to create a D3D device to see if the ddraw implementation supports
2685 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
2686 * doesn't support e.g. the IDirect3DTexture interfaces. */
2687 if (!(device = create_device(window, DDSCL_NORMAL)))
2689 skip("Failed to create a 3D device, skipping test.\n");
2690 DestroyWindow(window);
2691 return;
2693 IDirect3DDevice_Release(device);
2694 ddraw = create_ddraw();
2695 ok(!!ddraw, "Failed to create a ddraw object.\n");
2696 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2697 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
2699 memset(&surface_desc, 0, sizeof(surface_desc));
2700 surface_desc.dwSize = sizeof(surface_desc);
2701 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2702 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2703 surface_desc.dwWidth = 512;
2704 surface_desc.dwHeight = 512;
2705 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, (IDirectDrawSurface4 **)0xdeadbeef, NULL);
2706 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
2707 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2708 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
2710 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface4, tests, ARRAY_SIZE(tests));
2712 IDirectDrawSurface4_Release(surface);
2713 IDirectDraw4_Release(ddraw);
2714 DestroyWindow(window);
2717 static void test_device_qi(void)
2719 static const struct qi_test tests[] =
2721 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2722 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2723 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2724 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2725 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2726 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2727 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2728 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2729 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2730 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
2731 {&IID_IDirect3DDevice3, &IID_IDirect3DDevice3, S_OK },
2732 {&IID_IDirect3DDevice2, &IID_IDirect3DDevice3, S_OK },
2733 {&IID_IDirect3DDevice, &IID_IDirect3DDevice3, S_OK },
2734 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2735 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2736 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2737 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2738 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2739 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2740 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2741 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2742 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2743 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2744 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2745 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2746 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2747 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2748 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2749 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2750 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2751 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2752 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2753 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2754 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2755 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2756 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2757 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2758 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2759 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2760 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2761 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2762 {&IID_IUnknown, &IID_IDirect3DDevice3, S_OK },
2765 IDirect3DDevice3 *device;
2766 HWND window;
2768 window = create_window();
2769 if (!(device = create_device(window, DDSCL_NORMAL)))
2771 skip("Failed to create a 3D device, skipping test.\n");
2772 DestroyWindow(window);
2773 return;
2776 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice3, tests, ARRAY_SIZE(tests));
2778 IDirect3DDevice3_Release(device);
2779 DestroyWindow(window);
2782 static void test_wndproc(void)
2784 LONG_PTR proc, ddraw_proc;
2785 IDirectDraw4 *ddraw;
2786 WNDCLASSA wc = {0};
2787 HWND window;
2788 HRESULT hr;
2789 ULONG ref;
2791 static struct message messages[] =
2793 {WM_WINDOWPOSCHANGING, FALSE, 0},
2794 {WM_MOVE, FALSE, 0},
2795 {WM_SIZE, FALSE, 0},
2796 {WM_WINDOWPOSCHANGING, FALSE, 0},
2797 {WM_ACTIVATE, FALSE, 0},
2798 {WM_SETFOCUS, FALSE, 0},
2799 {0, FALSE, 0},
2802 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2803 ddraw = create_ddraw();
2804 ok(!!ddraw, "Failed to create a ddraw object.\n");
2806 wc.lpfnWndProc = test_proc;
2807 wc.lpszClassName = "ddraw_test_wndproc_wc";
2808 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2810 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2811 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2813 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2814 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2815 (LONG_PTR)test_proc, proc);
2816 expect_messages = messages;
2817 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2818 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2819 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2820 expect_messages = NULL;
2821 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2822 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix, got %#Ix.\n",
2823 (LONG_PTR)test_proc, proc);
2824 ref = IDirectDraw4_Release(ddraw);
2825 ok(!ref, "Unexpected refcount %lu.\n", ref);
2826 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2827 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2828 (LONG_PTR)test_proc, proc);
2830 /* DDSCL_NORMAL doesn't. */
2831 ddraw = create_ddraw();
2832 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2833 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2834 (LONG_PTR)test_proc, proc);
2835 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2836 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2837 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2838 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2839 (LONG_PTR)test_proc, proc);
2840 ref = IDirectDraw4_Release(ddraw);
2841 ok(!ref, "Unexpected refcount %lu.\n", ref);
2842 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2843 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2844 (LONG_PTR)test_proc, proc);
2846 /* The original window proc is only restored by ddraw if the current
2847 * window proc matches the one ddraw set. This also affects switching
2848 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2849 ddraw = create_ddraw();
2850 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2851 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2852 (LONG_PTR)test_proc, proc);
2853 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2854 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2855 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2856 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix, got %#Ix.\n",
2857 (LONG_PTR)test_proc, proc);
2858 ddraw_proc = proc;
2859 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2860 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2861 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2862 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2863 (LONG_PTR)test_proc, proc);
2864 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2865 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2866 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2867 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix, got %#Ix.\n",
2868 (LONG_PTR)test_proc, proc);
2869 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2870 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2871 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2872 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#Ix, got %#Ix.\n",
2873 (LONG_PTR)DefWindowProcA, proc);
2874 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2875 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2876 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, ddraw_proc);
2877 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#Ix, got %#Ix.\n",
2878 (LONG_PTR)DefWindowProcA, proc);
2879 ref = IDirectDraw4_Release(ddraw);
2880 ok(!ref, "Unexpected refcount %lu.\n", ref);
2881 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2882 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2883 (LONG_PTR)test_proc, proc);
2885 ddraw = create_ddraw();
2886 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2887 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2888 (LONG_PTR)test_proc, proc);
2889 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2890 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2891 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2892 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix, got %#Ix.\n",
2893 (LONG_PTR)test_proc, proc);
2894 ref = IDirectDraw4_Release(ddraw);
2895 ok(!ref, "Unexpected refcount %lu.\n", ref);
2896 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2897 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#Ix, got %#Ix.\n",
2898 (LONG_PTR)DefWindowProcA, proc);
2900 fix_wndproc(window, (LONG_PTR)test_proc);
2901 expect_messages = NULL;
2902 DestroyWindow(window);
2903 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2906 static void test_window_style(void)
2908 LONG style, exstyle, tmp, expected_style;
2909 RECT fullscreen_rect, r;
2910 HWND window, window2;
2911 IDirectDraw4 *ddraw;
2912 HRESULT hr;
2913 ULONG ref;
2914 BOOL ret;
2916 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2917 0, 0, 100, 100, 0, 0, 0, 0);
2918 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2919 0, 0, 50, 50, 0, 0, 0, 0);
2920 ddraw = create_ddraw();
2921 ok(!!ddraw, "Failed to create a ddraw object.\n");
2923 style = GetWindowLongA(window, GWL_STYLE);
2924 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2925 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2927 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2928 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2930 tmp = GetWindowLongA(window, GWL_STYLE);
2931 todo_wine ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2932 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2933 todo_wine ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2935 GetWindowRect(window, &r);
2936 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2937 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2938 GetClientRect(window, &r);
2939 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2941 ret = SetForegroundWindow(GetDesktopWindow());
2942 ok(ret, "Failed to set foreground window.\n");
2944 tmp = GetWindowLongA(window, GWL_STYLE);
2945 todo_wine ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2946 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2947 todo_wine ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2949 ret = SetForegroundWindow(window);
2950 ok(ret, "Failed to set foreground window.\n");
2951 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2952 * the next tests expect this. */
2953 ShowWindow(window, SW_HIDE);
2955 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2956 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2958 tmp = GetWindowLongA(window, GWL_STYLE);
2959 ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2960 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2961 ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2963 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_NOWINDOWCHANGES);
2964 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2966 tmp = GetWindowLongA(window, GWL_STYLE);
2967 todo_wine ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2968 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2969 todo_wine ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
2971 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2972 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2974 tmp = GetWindowLongA(window, GWL_STYLE);
2975 expected_style = style | WS_VISIBLE;
2976 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
2977 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2978 expected_style = exstyle | WS_EX_TOPMOST;
2979 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2981 ShowWindow(window, SW_HIDE);
2982 tmp = GetWindowLongA(window, GWL_STYLE);
2983 todo_wine ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2984 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2985 expected_style = exstyle | WS_EX_TOPMOST;
2986 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2988 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_NOWINDOWCHANGES);
2989 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
2991 tmp = GetWindowLongA(window, GWL_STYLE);
2992 ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
2993 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2994 expected_style = exstyle | WS_EX_TOPMOST;
2995 ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
2997 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2998 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3000 tmp = GetWindowLongA(window, GWL_STYLE);
3001 ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
3002 tmp = GetWindowLongA(window, GWL_EXSTYLE);
3003 expected_style = exstyle | WS_EX_TOPMOST;
3004 ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
3006 ret = SetForegroundWindow(window);
3007 ok(ret, "Failed to set foreground window.\n");
3009 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3010 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3012 tmp = GetWindowLongA(window, GWL_STYLE);
3013 expected_style = style | WS_VISIBLE;
3014 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
3015 tmp = GetWindowLongA(window, GWL_EXSTYLE);
3016 expected_style = exstyle | WS_EX_TOPMOST;
3017 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
3019 ShowWindow(window, SW_HIDE);
3020 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3021 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3023 tmp = GetWindowLongA(window, GWL_STYLE);
3024 ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
3025 tmp = GetWindowLongA(window, GWL_EXSTYLE);
3026 ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
3028 ShowWindow(window, SW_SHOW);
3029 ret = SetForegroundWindow(GetDesktopWindow());
3030 ok(ret, "Failed to set foreground window.\n");
3031 SetActiveWindow(window);
3032 ok(GetActiveWindow() == window, "Unexpected active window.\n");
3033 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3034 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3036 tmp = GetWindowLongA(window, GWL_STYLE);
3037 expected_style = style | WS_VISIBLE;
3038 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
3039 tmp = GetWindowLongA(window, GWL_EXSTYLE);
3040 todo_wine ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
3042 GetWindowRect(window, &r);
3043 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
3044 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
3046 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3047 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3049 SetWindowPos(window, NULL, 0, 0, 100, 100, SWP_NOZORDER | SWP_NOACTIVATE);
3050 GetWindowRect(window, &r);
3051 ok(!EqualRect(&r, &fullscreen_rect), "Window resize failed? got %s.\n",
3052 wine_dbgstr_rect(&r));
3054 ret = SetForegroundWindow(window2);
3055 ok(ret, "Failed to set foreground window.\n");
3056 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3057 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3059 tmp = GetWindowLongA(window, GWL_STYLE);
3060 expected_style = style | WS_VISIBLE;
3061 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
3062 tmp = GetWindowLongA(window, GWL_EXSTYLE);
3063 todo_wine ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
3065 GetWindowRect(window, &r);
3066 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
3067 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
3069 ret = SetForegroundWindow(window);
3070 ok(ret, "Failed to set foreground window.\n");
3071 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3072 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3074 tmp = GetWindowLongA(window, GWL_STYLE);
3075 expected_style = style | WS_VISIBLE;
3076 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
3077 tmp = GetWindowLongA(window, GWL_EXSTYLE);
3078 expected_style = exstyle | WS_EX_TOPMOST;
3079 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
3081 ShowWindow(window, SW_HIDE);
3082 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3083 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3085 tmp = GetWindowLongA(window, GWL_STYLE);
3086 ok(tmp == style, "Expected window style %#lx, got %#lx.\n", style, tmp);
3087 tmp = GetWindowLongA(window, GWL_EXSTYLE);
3088 ok(tmp == exstyle, "Expected window extended style %#lx, got %#lx.\n", exstyle, tmp);
3090 ShowWindow(window, SW_SHOW);
3091 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3092 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3094 tmp = GetWindowLongA(window, GWL_STYLE);
3095 expected_style = style | WS_VISIBLE;
3096 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
3097 tmp = GetWindowLongA(window, GWL_EXSTYLE);
3098 expected_style = exstyle | WS_EX_TOPMOST;
3099 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
3101 ret = SetForegroundWindow(GetDesktopWindow());
3102 ok(ret, "Failed to set foreground window.\n");
3103 tmp = GetWindowLongA(window, GWL_STYLE);
3104 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
3105 todo_wine ok(tmp == expected_style, "Expected window style %#lx, got %#lx.\n", expected_style, tmp);
3106 tmp = GetWindowLongA(window, GWL_EXSTYLE);
3107 expected_style = exstyle | WS_EX_TOPMOST;
3108 todo_wine ok(tmp == expected_style, "Expected window extended style %#lx, got %#lx.\n", expected_style, tmp);
3110 ref = IDirectDraw4_Release(ddraw);
3111 ok(!ref, "Unexpected refcount %lu.\n", ref);
3113 DestroyWindow(window2);
3114 DestroyWindow(window);
3117 static void test_redundant_mode_set(void)
3119 DDSURFACEDESC2 surface_desc = {0};
3120 IDirectDraw4 *ddraw;
3121 RECT q, r, s;
3122 HWND window;
3123 HRESULT hr;
3124 ULONG ref;
3126 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3127 0, 0, 100, 100, 0, 0, 0, 0);
3128 ddraw = create_ddraw();
3129 ok(!!ddraw, "Failed to create a ddraw object.\n");
3131 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3132 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3134 surface_desc.dwSize = sizeof(surface_desc);
3135 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
3136 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#lx.\n", hr);
3138 hr = IDirectDraw4_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
3139 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
3140 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#lx.\n", hr);
3142 GetWindowRect(window, &q);
3143 r = q;
3144 r.right /= 2;
3145 r.bottom /= 2;
3146 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
3147 GetWindowRect(window, &s);
3148 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
3150 hr = IDirectDraw4_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
3151 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
3152 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#lx.\n", hr);
3154 GetWindowRect(window, &s);
3155 ok(EqualRect(&r, &s) || broken(EqualRect(&q, &s) /* Windows 10 */),
3156 "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
3158 ref = IDirectDraw4_Release(ddraw);
3159 ok(!ref, "Unexpected refcount %lu.\n", ref);
3161 DestroyWindow(window);
3164 static SIZE screen_size, screen_size2;
3166 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3168 if (message == WM_SIZE)
3170 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
3171 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
3174 return test_proc(hwnd, message, wparam, lparam);
3177 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3179 if (message == WM_SIZE)
3181 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
3182 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
3185 return test_proc(hwnd, message, wparam, lparam);
3188 struct test_coop_level_mode_set_enum_param
3190 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
3193 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface_desc, void *context)
3195 struct test_coop_level_mode_set_enum_param *param = context;
3197 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
3198 return DDENUMRET_OK;
3199 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
3200 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
3201 return DDENUMRET_OK;
3203 if (!param->ddraw_width)
3205 param->ddraw_width = surface_desc->dwWidth;
3206 param->ddraw_height = surface_desc->dwHeight;
3207 return DDENUMRET_OK;
3209 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
3210 return DDENUMRET_OK;
3212 /* The docs say the DDENUMRET_CANCEL below cancels the enumeration, so the check should be
3213 * redundant. However, since Windows 10 this no longer works and the enumeration continues
3214 * until all supported modes are enumerated. Win8 and earlier do cancel.
3216 * Unrelatedly, some testbot machines report high res modes like 1920x1080, but suffer from
3217 * some problems when we actually try to set them (w10pro64 and its localization siblings).
3218 * Try to stay below the registry mode if possible. */
3219 if (!param->user32_width || (surface_desc->dwWidth < registry_mode.dmPelsWidth
3220 && surface_desc->dwHeight < registry_mode.dmPelsHeight))
3222 param->user32_width = surface_desc->dwWidth;
3223 param->user32_height = surface_desc->dwHeight;
3225 return DDENUMRET_CANCEL;
3228 static void test_coop_level_mode_set(void)
3230 DEVMODEW *original_modes = NULL, devmode, devmode2;
3231 unsigned int display_count = 0;
3232 IDirectDrawSurface4 *primary;
3233 RECT registry_rect, ddraw_rect, user32_rect, r;
3234 IDirectDraw4 *ddraw;
3235 DDSURFACEDESC2 ddsd;
3236 WNDCLASSA wc = {0};
3237 HWND window, window2;
3238 HRESULT hr;
3239 ULONG ref;
3240 MSG msg;
3241 struct test_coop_level_mode_set_enum_param param;
3242 BOOL ret;
3243 LONG change_ret;
3245 static const struct message exclusive_messages[] =
3247 {WM_WINDOWPOSCHANGING, FALSE, 0},
3248 {WM_WINDOWPOSCHANGED, FALSE, 0},
3249 {WM_SIZE, FALSE, 0},
3250 {WM_DISPLAYCHANGE, FALSE, 0},
3251 {0, FALSE, 0},
3253 static const struct message exclusive_focus_loss_messages[] =
3255 {WM_ACTIVATE, TRUE, WA_INACTIVE, DD_OK},
3256 {WM_WINDOWPOSCHANGING, FALSE, 0, DD_OK}, /* Window resize due to mode change. */
3257 {WM_WINDOWPOSCHANGED, FALSE, 0, DD_OK},
3258 {WM_SIZE, TRUE, SIZE_RESTORED, DD_OK}, /* Generated by DefWindowProc. */
3259 {WM_DISPLAYCHANGE, FALSE, 0, DD_OK},
3260 {WM_KILLFOCUS, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
3261 {WM_WINDOWPOSCHANGING, FALSE, 0, DDERR_NOEXCLUSIVEMODE}, /* Window minimized. */
3262 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
3263 * SW_MINIMIZED, causing a recursive window activation that does not
3264 * produce the same result in Wine yet. Ignore the difference for now.
3265 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
3266 {WM_WINDOWPOSCHANGED, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
3267 {WM_MOVE, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
3268 {WM_SIZE, TRUE, SIZE_MINIMIZED, DDERR_NOEXCLUSIVEMODE},
3269 {WM_ACTIVATEAPP, TRUE, FALSE, DDERR_NOEXCLUSIVEMODE},
3270 {0, FALSE, 0, 0},
3272 static const struct message exclusive_focus_restore_messages[] =
3274 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
3275 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
3276 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
3277 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
3278 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
3279 /* Native redundantly sets the window size here. */
3280 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
3281 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
3282 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
3283 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
3284 {0, FALSE, 0},
3286 static const struct message sc_restore_messages[] =
3288 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
3289 {WM_WINDOWPOSCHANGING, FALSE, 0},
3290 {WM_WINDOWPOSCHANGED, FALSE, 0},
3291 {WM_SIZE, TRUE, SIZE_RESTORED},
3292 {0, FALSE, 0},
3294 static const struct message sc_minimize_messages[] =
3296 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
3297 {WM_WINDOWPOSCHANGING, FALSE, 0},
3298 {WM_WINDOWPOSCHANGED, FALSE, 0},
3299 {WM_SIZE, TRUE, SIZE_MINIMIZED},
3300 {0, FALSE, 0},
3302 static const struct message sc_maximize_messages[] =
3304 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
3305 {WM_WINDOWPOSCHANGING, FALSE, 0},
3306 {WM_WINDOWPOSCHANGED, FALSE, 0},
3307 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
3308 {0, FALSE, 0},
3311 static const struct message normal_messages[] =
3313 {WM_DISPLAYCHANGE, FALSE, 0},
3314 {0, FALSE, 0},
3317 memset(&devmode, 0, sizeof(devmode));
3318 devmode.dmSize = sizeof(devmode);
3319 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3320 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3321 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3322 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
3323 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
3324 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3326 ret = save_display_modes(&original_modes, &display_count);
3327 ok(ret, "Failed to save original display modes.\n");
3329 ddraw = create_ddraw();
3330 ok(!!ddraw, "Failed to create a ddraw object.\n");
3332 memset(&param, 0, sizeof(param));
3333 hr = IDirectDraw4_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
3334 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#lx.\n", hr);
3335 ref = IDirectDraw4_Release(ddraw);
3336 ok(!ref, "Unexpected refcount %lu.\n", ref);
3338 if (!param.user32_height)
3340 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
3341 heap_free(original_modes);
3342 return;
3345 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3346 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
3347 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
3349 memset(&devmode, 0, sizeof(devmode));
3350 devmode.dmSize = sizeof(devmode);
3351 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3352 devmode.dmPelsWidth = param.user32_width;
3353 devmode.dmPelsHeight = param.user32_height;
3354 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3355 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3357 ddraw = create_ddraw();
3358 ok(!!ddraw, "Failed to create a ddraw object.\n");
3360 wc.lpfnWndProc = mode_set_proc;
3361 wc.lpszClassName = "ddraw_test_wndproc_wc";
3362 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3363 wc.lpfnWndProc = mode_set_proc2;
3364 wc.lpszClassName = "ddraw_test_wndproc_wc2";
3365 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3367 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
3368 0, 0, 100, 100, 0, 0, 0, 0);
3369 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
3370 0, 0, 100, 100, 0, 0, 0, 0);
3372 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3373 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3375 GetWindowRect(window, &r);
3376 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
3377 wine_dbgstr_rect(&r));
3379 memset(&ddsd, 0, sizeof(ddsd));
3380 ddsd.dwSize = sizeof(ddsd);
3381 ddsd.dwFlags = DDSD_CAPS;
3382 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3384 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3385 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3386 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3387 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3388 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %lu, got %lu.\n",
3389 param.user32_width, ddsd.dwWidth);
3390 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %lu, got %lu.\n",
3391 param.user32_height, ddsd.dwHeight);
3393 GetWindowRect(window, &r);
3394 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
3395 wine_dbgstr_rect(&r));
3397 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3398 expect_messages = exclusive_messages;
3399 screen_size.cx = 0;
3400 screen_size.cy = 0;
3402 hr = IDirectDrawSurface4_IsLost(primary);
3403 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3404 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3405 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3406 hr = IDirectDrawSurface4_IsLost(primary);
3407 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3409 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3410 expect_messages = NULL;
3411 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
3412 "Expected screen size %lux%lu, got %lux%lu.\n",
3413 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
3415 GetWindowRect(window, &r);
3416 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3417 wine_dbgstr_rect(&r));
3419 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3420 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3421 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %lu, got %lu.\n",
3422 param.user32_width, ddsd.dwWidth);
3423 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %lu, got %lu.\n",
3424 param.user32_height, ddsd.dwHeight);
3425 IDirectDrawSurface4_Release(primary);
3427 memset(&ddsd, 0, sizeof(ddsd));
3428 ddsd.dwSize = sizeof(ddsd);
3429 ddsd.dwFlags = DDSD_CAPS;
3430 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3432 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3433 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3434 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3435 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3436 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3437 param.ddraw_width, ddsd.dwWidth);
3438 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3439 param.ddraw_height, ddsd.dwHeight);
3441 GetWindowRect(window, &r);
3442 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3443 wine_dbgstr_rect(&r));
3445 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3446 expect_messages = exclusive_messages;
3447 screen_size.cx = 0;
3448 screen_size.cy = 0;
3450 hr = IDirectDrawSurface4_IsLost(primary);
3451 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3452 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3453 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3454 hr = IDirectDrawSurface4_IsLost(primary);
3455 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3457 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3458 expect_messages = NULL;
3459 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
3460 "Expected screen size %lux%lu, got %lux%lu.\n",
3461 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
3463 GetWindowRect(window, &r);
3464 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
3465 wine_dbgstr_rect(&r));
3467 expect_messages = exclusive_focus_loss_messages;
3468 focus_test_ddraw = ddraw;
3469 ret = SetForegroundWindow(GetDesktopWindow());
3470 ok(ret, "Failed to set foreground window.\n");
3471 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3472 focus_test_ddraw = NULL;
3474 memset(&devmode, 0, sizeof(devmode));
3475 devmode.dmSize = sizeof(devmode);
3476 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3477 ok(ret, "Failed to get display mode.\n");
3478 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3479 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpected screen size %lux%lu.\n",
3480 devmode.dmPelsWidth, devmode.dmPelsHeight);
3482 expect_messages = exclusive_focus_restore_messages;
3483 ShowWindow(window, SW_RESTORE);
3484 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3486 GetWindowRect(window, &r);
3487 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3488 wine_dbgstr_rect(&r));
3489 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3490 ok(ret, "Failed to get display mode.\n");
3491 ok(devmode.dmPelsWidth == param.ddraw_width
3492 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpected screen size %lux%lu.\n",
3493 devmode.dmPelsWidth, devmode.dmPelsHeight);
3495 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3496 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3497 /* Normally the primary should be restored here. Unfortunately this causes the
3498 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
3499 * testbot. Another Restore call would presumably avoid the crash, but it also moots
3500 * the point of the GetSurfaceDesc call. */
3502 expect_messages = sc_minimize_messages;
3503 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3504 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3505 expect_messages = NULL;
3507 expect_messages = sc_restore_messages;
3508 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
3509 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3510 expect_messages = NULL;
3512 expect_messages = sc_maximize_messages;
3513 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3514 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3515 expect_messages = NULL;
3517 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3518 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3520 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3521 expect_messages = exclusive_messages;
3522 screen_size.cx = 0;
3523 screen_size.cy = 0;
3525 hr = IDirectDrawSurface4_IsLost(primary);
3526 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3527 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3528 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#lx.\n", hr);
3529 hr = IDirectDrawSurface4_IsLost(primary);
3530 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3532 flaky /* win8 */
3533 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3534 expect_messages = NULL;
3535 flaky /* win8 */
3536 ok(screen_size.cx == registry_mode.dmPelsWidth
3537 && screen_size.cy == registry_mode.dmPelsHeight,
3538 "Expected screen size %lux%lu, got %lux%lu.\n",
3539 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
3541 GetWindowRect(window, &r);
3542 flaky /* win8 */
3543 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3544 wine_dbgstr_rect(&r));
3546 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3547 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3548 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3549 param.ddraw_width, ddsd.dwWidth);
3550 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3551 param.ddraw_height, ddsd.dwHeight);
3552 IDirectDrawSurface4_Release(primary);
3554 /* For Wine. */
3555 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3556 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3558 memset(&ddsd, 0, sizeof(ddsd));
3559 ddsd.dwSize = sizeof(ddsd);
3560 ddsd.dwFlags = DDSD_CAPS;
3561 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3563 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3564 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3565 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3566 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3567 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3568 registry_mode.dmPelsWidth, ddsd.dwWidth);
3569 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3570 registry_mode.dmPelsHeight, ddsd.dwHeight);
3572 GetWindowRect(window, &r);
3573 flaky /* win8 */
3574 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3575 wine_dbgstr_rect(&r));
3577 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3578 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3580 GetWindowRect(window, &r);
3581 flaky /* win8 */
3582 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3583 wine_dbgstr_rect(&r));
3585 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3586 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3587 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3588 registry_mode.dmPelsWidth, ddsd.dwWidth);
3589 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3590 registry_mode.dmPelsHeight, ddsd.dwHeight);
3591 IDirectDrawSurface4_Release(primary);
3593 memset(&ddsd, 0, sizeof(ddsd));
3594 ddsd.dwSize = sizeof(ddsd);
3595 ddsd.dwFlags = DDSD_CAPS;
3596 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3598 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3599 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3600 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3601 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3602 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3603 registry_mode.dmPelsWidth, ddsd.dwWidth);
3604 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3605 registry_mode.dmPelsHeight, ddsd.dwHeight);
3607 GetWindowRect(window, &r);
3608 flaky /* win8 */
3609 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3610 wine_dbgstr_rect(&r));
3612 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3613 expect_messages = normal_messages;
3614 screen_size.cx = 0;
3615 screen_size.cy = 0;
3617 hr = IDirectDrawSurface4_IsLost(primary);
3618 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3619 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3620 devmode.dmPelsWidth = param.user32_width;
3621 devmode.dmPelsHeight = param.user32_height;
3622 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3623 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3624 hr = IDirectDrawSurface4_IsLost(primary);
3625 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3627 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3628 expect_messages = NULL;
3629 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3631 GetWindowRect(window, &r);
3632 flaky /* win8 */
3633 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3634 wine_dbgstr_rect(&r));
3636 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3637 expect_messages = normal_messages;
3638 screen_size.cx = 0;
3639 screen_size.cy = 0;
3641 hr = IDirectDrawSurface4_Restore(primary);
3642 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
3643 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3644 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3645 hr = IDirectDrawSurface4_Restore(primary);
3646 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
3647 hr = IDirectDrawSurface4_IsLost(primary);
3648 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3650 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3651 expect_messages = NULL;
3652 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3654 GetWindowRect(window, &r);
3655 flaky /* win8 */
3656 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3657 wine_dbgstr_rect(&r));
3659 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3660 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3661 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3662 registry_mode.dmPelsWidth, ddsd.dwWidth);
3663 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3664 registry_mode.dmPelsHeight, ddsd.dwHeight);
3665 IDirectDrawSurface4_Release(primary);
3667 memset(&ddsd, 0, sizeof(ddsd));
3668 ddsd.dwSize = sizeof(ddsd);
3669 ddsd.dwFlags = DDSD_CAPS;
3670 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3672 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3673 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3674 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3675 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3676 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3677 param.ddraw_width, ddsd.dwWidth);
3678 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3679 param.ddraw_height, ddsd.dwHeight);
3681 GetWindowRect(window, &r);
3682 flaky /* win8 */
3683 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3684 wine_dbgstr_rect(&r));
3686 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3687 expect_messages = normal_messages;
3688 screen_size.cx = 0;
3689 screen_size.cy = 0;
3691 hr = IDirectDrawSurface4_IsLost(primary);
3692 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3693 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3694 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#lx.\n", hr);
3695 hr = IDirectDrawSurface4_IsLost(primary);
3696 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3698 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3699 expect_messages = NULL;
3700 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3702 GetWindowRect(window, &r);
3703 flaky /* win8 */
3704 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3705 wine_dbgstr_rect(&r));
3707 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3708 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3709 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3710 param.ddraw_width, ddsd.dwWidth);
3711 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3712 param.ddraw_height, ddsd.dwHeight);
3713 IDirectDrawSurface4_Release(primary);
3715 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3716 ok(ret, "Failed to get display mode.\n");
3717 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3718 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3719 "Expected resolution %lux%lu, got %lux%lu.\n",
3720 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3721 devmode.dmPelsWidth, devmode.dmPelsHeight);
3722 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3723 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3725 memset(&ddsd, 0, sizeof(ddsd));
3726 ddsd.dwSize = sizeof(ddsd);
3727 ddsd.dwFlags = DDSD_CAPS;
3728 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3730 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3731 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3732 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3733 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3734 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3735 registry_mode.dmPelsWidth, ddsd.dwWidth);
3736 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3737 registry_mode.dmPelsHeight, ddsd.dwHeight);
3739 GetWindowRect(window, &r);
3740 flaky /* win8 */
3741 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3742 wine_dbgstr_rect(&r));
3744 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
3745 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
3746 * not DDSCL_FULLSCREEN. */
3747 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3748 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3750 GetWindowRect(window, &r);
3751 flaky /* win8 */
3752 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3753 wine_dbgstr_rect(&r));
3755 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3756 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3757 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3758 registry_mode.dmPelsWidth, ddsd.dwWidth);
3759 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3760 registry_mode.dmPelsHeight, ddsd.dwHeight);
3761 IDirectDrawSurface4_Release(primary);
3763 memset(&ddsd, 0, sizeof(ddsd));
3764 ddsd.dwSize = sizeof(ddsd);
3765 ddsd.dwFlags = DDSD_CAPS;
3766 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3768 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3769 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3770 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3771 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3772 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3773 registry_mode.dmPelsWidth, ddsd.dwWidth);
3774 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3775 registry_mode.dmPelsHeight, ddsd.dwHeight);
3777 GetWindowRect(window, &r);
3778 flaky /* win8 */
3779 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3780 wine_dbgstr_rect(&r));
3782 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3783 expect_messages = normal_messages;
3784 screen_size.cx = 0;
3785 screen_size.cy = 0;
3787 hr = IDirectDrawSurface4_IsLost(primary);
3788 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3789 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3790 devmode.dmPelsWidth = param.user32_width;
3791 devmode.dmPelsHeight = param.user32_height;
3792 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3793 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3794 hr = IDirectDrawSurface4_IsLost(primary);
3795 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3797 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3798 expect_messages = NULL;
3799 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3801 GetWindowRect(window, &r);
3802 flaky /* win8 */
3803 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3804 wine_dbgstr_rect(&r));
3806 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3807 expect_messages = normal_messages;
3808 screen_size.cx = 0;
3809 screen_size.cy = 0;
3811 hr = IDirectDrawSurface4_Restore(primary);
3812 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
3813 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3814 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3815 hr = IDirectDrawSurface4_Restore(primary);
3816 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
3817 hr = IDirectDrawSurface4_IsLost(primary);
3818 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3820 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3821 expect_messages = NULL;
3822 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3824 GetWindowRect(window, &r);
3825 flaky /* win8 */
3826 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3827 wine_dbgstr_rect(&r));
3829 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3830 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3831 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3832 registry_mode.dmPelsWidth, ddsd.dwWidth);
3833 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3834 registry_mode.dmPelsHeight, ddsd.dwHeight);
3835 IDirectDrawSurface4_Release(primary);
3837 memset(&ddsd, 0, sizeof(ddsd));
3838 ddsd.dwSize = sizeof(ddsd);
3839 ddsd.dwFlags = DDSD_CAPS;
3840 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3842 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3843 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3844 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3845 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3846 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3847 param.ddraw_width, ddsd.dwWidth);
3848 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3849 param.ddraw_height, ddsd.dwHeight);
3851 GetWindowRect(window, &r);
3852 flaky /* win8 */
3853 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3854 wine_dbgstr_rect(&r));
3856 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3857 expect_messages = normal_messages;
3858 screen_size.cx = 0;
3859 screen_size.cy = 0;
3861 hr = IDirectDrawSurface4_IsLost(primary);
3862 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
3863 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3864 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#lx.\n", hr);
3865 hr = IDirectDrawSurface4_IsLost(primary);
3866 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
3868 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3869 expect_messages = NULL;
3870 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n", screen_size.cx, screen_size.cy);
3872 GetWindowRect(window, &r);
3873 flaky /* win8 */
3874 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3875 wine_dbgstr_rect(&r));
3877 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3878 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3879 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3880 param.ddraw_width, ddsd.dwWidth);
3881 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3882 param.ddraw_height, ddsd.dwHeight);
3883 IDirectDrawSurface4_Release(primary);
3885 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3886 ok(ret, "Failed to get display mode.\n");
3887 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3888 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3889 "Expected resolution %lux%lu, got %lux%lu.\n",
3890 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3891 devmode.dmPelsWidth, devmode.dmPelsHeight);
3892 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3893 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3895 memset(&ddsd, 0, sizeof(ddsd));
3896 ddsd.dwSize = sizeof(ddsd);
3897 ddsd.dwFlags = DDSD_CAPS;
3898 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3900 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3901 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3902 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3903 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3904 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3905 registry_mode.dmPelsWidth, ddsd.dwWidth);
3906 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3907 registry_mode.dmPelsHeight, ddsd.dwHeight);
3908 IDirectDrawSurface4_Release(primary);
3910 GetWindowRect(window, &r);
3911 flaky /* win8 */
3912 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3913 wine_dbgstr_rect(&r));
3915 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3916 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3917 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3918 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3919 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3921 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3922 expect_messages = exclusive_messages;
3923 screen_size.cx = 0;
3924 screen_size.cy = 0;
3926 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3927 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3929 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3930 expect_messages = NULL;
3931 ok(screen_size.cx == registry_mode.dmPelsWidth
3932 && screen_size.cy == registry_mode.dmPelsHeight,
3933 "Expected screen size %lux%lu, got %lux%lu.\n",
3934 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3935 screen_size.cx, screen_size.cy);
3937 GetWindowRect(window, &r);
3938 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3939 wine_dbgstr_rect(&r));
3941 memset(&ddsd, 0, sizeof(ddsd));
3942 ddsd.dwSize = sizeof(ddsd);
3943 ddsd.dwFlags = DDSD_CAPS;
3944 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3946 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3947 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3948 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3949 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3950 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
3951 registry_mode.dmPelsWidth, ddsd.dwWidth);
3952 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
3953 registry_mode.dmPelsHeight, ddsd.dwHeight);
3954 IDirectDrawSurface4_Release(primary);
3956 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3957 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3958 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3959 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3960 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3962 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3963 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3965 memset(&ddsd, 0, sizeof(ddsd));
3966 ddsd.dwSize = sizeof(ddsd);
3967 ddsd.dwFlags = DDSD_CAPS;
3968 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3970 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
3971 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
3972 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
3973 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3974 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %lu, got %lu.\n",
3975 param.ddraw_width, ddsd.dwWidth);
3976 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %lu, got %lu.\n",
3977 param.ddraw_height, ddsd.dwHeight);
3978 IDirectDrawSurface4_Release(primary);
3980 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
3981 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#lx.\n", hr);
3983 /* If the window is changed at the same time, messages are sent to the new window. */
3984 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3985 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3986 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3987 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
3989 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3990 expect_messages = exclusive_messages;
3991 screen_size.cx = 0;
3992 screen_size.cy = 0;
3993 screen_size2.cx = 0;
3994 screen_size2.cy = 0;
3996 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3997 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
3999 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
4000 expect_messages = NULL;
4001 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %lux%lu.\n",
4002 screen_size.cx, screen_size.cy);
4003 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
4004 "Expected screen size 2 %lux%lu, got %lux%lu.\n",
4005 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
4007 GetWindowRect(window, &r);
4008 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
4009 wine_dbgstr_rect(&r));
4010 GetWindowRect(window2, &r);
4011 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
4012 wine_dbgstr_rect(&r));
4014 memset(&ddsd, 0, sizeof(ddsd));
4015 ddsd.dwSize = sizeof(ddsd);
4016 ddsd.dwFlags = DDSD_CAPS;
4017 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4019 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
4020 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
4021 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
4022 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
4023 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %lu, got %lu.\n",
4024 registry_mode.dmPelsWidth, ddsd.dwWidth);
4025 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %lu, got %lu.\n",
4026 registry_mode.dmPelsHeight, ddsd.dwHeight);
4027 IDirectDrawSurface4_Release(primary);
4029 ref = IDirectDraw4_Release(ddraw);
4030 ok(!ref, "Unexpected refcount %lu.\n", ref);
4032 GetWindowRect(window, &r);
4033 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
4034 wine_dbgstr_rect(&r));
4036 ret = restore_display_modes(original_modes, display_count);
4037 ok(ret, "Failed to restore display modes.\n");
4039 /* Test that no mode restorations if no mode changes happened */
4040 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
4041 devmode.dmPelsWidth = param.user32_width;
4042 devmode.dmPelsHeight = param.user32_height;
4043 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
4044 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %ld.\n", change_ret);
4046 ddraw = create_ddraw();
4047 ok(!!ddraw, "Failed to create a ddraw object.\n");
4048 ref = IDirectDraw4_Release(ddraw);
4049 ok(!ref, "Unexpected refcount %lu.\n", ref);
4051 memset(&devmode2, 0, sizeof(devmode2));
4052 devmode2.dmSize = sizeof(devmode2);
4053 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
4054 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4055 ok(compare_mode_rect(&devmode2, &registry_mode), "Got a different mode.\n");
4056 ret = restore_display_modes(original_modes, display_count);
4057 ok(ret, "Failed to restore display modes.\n");
4059 /* Test that no mode restorations if no mode changes happened with fullscreen ddraw objects */
4060 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
4061 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %ld.\n", change_ret);
4063 ddraw = create_ddraw();
4064 ok(!!ddraw, "Failed to create a ddraw object.\n");
4065 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4066 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
4067 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4068 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
4069 ref = IDirectDraw4_Release(ddraw);
4070 ok(!ref, "Unexpected refcount %lu.\n", ref);
4072 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
4073 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4074 ok(compare_mode_rect(&devmode2, &registry_mode), "Got a different mode.\n");
4075 ret = restore_display_modes(original_modes, display_count);
4076 ok(ret, "Failed to restore display modes.\n");
4078 /* Test that mode restorations use display settings in the registry after ddraw object releases
4079 * if SetDisplayMode() was called */
4080 ddraw = create_ddraw();
4081 ok(!!ddraw, "Failed to create a ddraw object.\n");
4082 hr = set_display_mode(ddraw, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4083 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4085 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
4086 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %ld.\n", change_ret);
4088 ref = IDirectDraw4_Release(ddraw);
4089 ok(!ref, "Unexpected refcount %lu.\n", ref);
4091 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
4092 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4093 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
4094 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
4095 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4096 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
4097 ret = restore_display_modes(original_modes, display_count);
4098 ok(ret, "Failed to restore display modes.\n");
4100 /* Test that mode restorations use display settings in the registry after RestoreDisplayMode() */
4101 ddraw = create_ddraw();
4102 ok(!!ddraw, "Failed to create a ddraw object.\n");
4103 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
4104 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4106 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
4107 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %ld.\n", change_ret);
4109 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
4110 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#lx.\n", hr);
4112 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
4113 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4114 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
4115 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
4116 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4117 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
4119 ref = IDirectDraw4_Release(ddraw);
4120 ok(!ref, "Unexpected refcount %lu.\n", ref);
4122 expect_messages = NULL;
4123 DestroyWindow(window);
4124 DestroyWindow(window2);
4125 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
4126 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
4127 ret = restore_display_modes(original_modes, display_count);
4128 ok(ret, "Failed to restore display modes.\n");
4129 heap_free(original_modes);
4132 static void test_coop_level_mode_set_multi(void)
4134 DEVMODEW old_devmode, devmode, devmode2, devmode3, *original_modes = NULL;
4135 unsigned int mode_idx = 0, display_idx, display_count = 0;
4136 WCHAR second_monitor_name[CCHDEVICENAME];
4137 IDirectDraw4 *ddraw1, *ddraw2;
4138 LONG change_ret;
4139 UINT w, h;
4140 HWND window;
4141 HRESULT hr;
4142 ULONG ref;
4143 BOOL ret;
4145 memset(&devmode, 0, sizeof(devmode));
4146 devmode.dmSize = sizeof(devmode);
4147 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4148 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4149 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
4150 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
4151 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4152 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
4154 ret = save_display_modes(&original_modes, &display_count);
4155 ok(ret, "Failed to save original display modes.\n");
4157 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4158 0, 0, 100, 100, 0, 0, 0, 0);
4159 ddraw1 = create_ddraw();
4160 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4162 /* With just a single ddraw object, the display mode is restored on
4163 * release. */
4164 hr = set_display_mode(ddraw1, 800, 600);
4165 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4166 w = GetSystemMetrics(SM_CXSCREEN);
4167 ok(w == 800, "Got unexpected screen width %u.\n", w);
4168 h = GetSystemMetrics(SM_CYSCREEN);
4169 ok(h == 600, "Got unexpected screen height %u.\n", h);
4171 ref = IDirectDraw4_Release(ddraw1);
4172 ok(!ref, "Unexpected refcount %lu.\n", ref);
4173 w = GetSystemMetrics(SM_CXSCREEN);
4174 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4175 h = GetSystemMetrics(SM_CYSCREEN);
4176 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4178 /* When there are multiple ddraw objects, the display mode is restored to
4179 * the initial mode, before the first SetDisplayMode() call. */
4180 ddraw1 = create_ddraw();
4181 hr = set_display_mode(ddraw1, 800, 600);
4182 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4183 w = GetSystemMetrics(SM_CXSCREEN);
4184 ok(w == 800, "Got unexpected screen width %u.\n", w);
4185 h = GetSystemMetrics(SM_CYSCREEN);
4186 ok(h == 600, "Got unexpected screen height %u.\n", h);
4188 ddraw2 = create_ddraw();
4189 hr = set_display_mode(ddraw2, 640, 480);
4190 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4191 w = GetSystemMetrics(SM_CXSCREEN);
4192 ok(w == 640, "Got unexpected screen width %u.\n", w);
4193 h = GetSystemMetrics(SM_CYSCREEN);
4194 ok(h == 480, "Got unexpected screen height %u.\n", h);
4196 ref = IDirectDraw4_Release(ddraw2);
4197 ok(!ref, "Unexpected refcount %lu.\n", ref);
4198 w = GetSystemMetrics(SM_CXSCREEN);
4199 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4200 h = GetSystemMetrics(SM_CYSCREEN);
4201 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4203 ref = IDirectDraw4_Release(ddraw1);
4204 ok(!ref, "Unexpected refcount %lu.\n", ref);
4205 w = GetSystemMetrics(SM_CXSCREEN);
4206 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4207 h = GetSystemMetrics(SM_CYSCREEN);
4208 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4210 /* Regardless of release ordering. */
4211 ddraw1 = create_ddraw();
4212 hr = set_display_mode(ddraw1, 800, 600);
4213 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4214 w = GetSystemMetrics(SM_CXSCREEN);
4215 ok(w == 800, "Got unexpected screen width %u.\n", w);
4216 h = GetSystemMetrics(SM_CYSCREEN);
4217 ok(h == 600, "Got unexpected screen height %u.\n", h);
4219 ddraw2 = create_ddraw();
4220 hr = set_display_mode(ddraw2, 640, 480);
4221 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4222 w = GetSystemMetrics(SM_CXSCREEN);
4223 ok(w == 640, "Got unexpected screen width %u.\n", w);
4224 h = GetSystemMetrics(SM_CYSCREEN);
4225 ok(h == 480, "Got unexpected screen height %u.\n", h);
4227 ref = IDirectDraw4_Release(ddraw1);
4228 ok(!ref, "Unexpected refcount %lu.\n", ref);
4229 w = GetSystemMetrics(SM_CXSCREEN);
4230 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4231 h = GetSystemMetrics(SM_CYSCREEN);
4232 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4234 ref = IDirectDraw4_Release(ddraw2);
4235 ok(!ref, "Unexpected refcount %lu.\n", ref);
4236 w = GetSystemMetrics(SM_CXSCREEN);
4237 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4238 h = GetSystemMetrics(SM_CYSCREEN);
4239 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4241 /* But only for ddraw objects that called SetDisplayMode(). */
4242 ddraw1 = create_ddraw();
4243 ddraw2 = create_ddraw();
4244 hr = set_display_mode(ddraw2, 640, 480);
4245 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4246 w = GetSystemMetrics(SM_CXSCREEN);
4247 ok(w == 640, "Got unexpected screen width %u.\n", w);
4248 h = GetSystemMetrics(SM_CYSCREEN);
4249 ok(h == 480, "Got unexpected screen height %u.\n", h);
4251 ref = IDirectDraw4_Release(ddraw1);
4252 ok(!ref, "Unexpected refcount %lu.\n", ref);
4253 w = GetSystemMetrics(SM_CXSCREEN);
4254 ok(w == 640, "Got unexpected screen width %u.\n", w);
4255 h = GetSystemMetrics(SM_CYSCREEN);
4256 ok(h == 480, "Got unexpected screen height %u.\n", h);
4258 ref = IDirectDraw4_Release(ddraw2);
4259 ok(!ref, "Unexpected refcount %lu.\n", ref);
4260 w = GetSystemMetrics(SM_CXSCREEN);
4261 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4262 h = GetSystemMetrics(SM_CYSCREEN);
4263 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4265 /* If there's a ddraw object that's currently in exclusive mode, it blocks
4266 * restoring the display mode. */
4267 ddraw1 = create_ddraw();
4268 hr = set_display_mode(ddraw1, 800, 600);
4269 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4270 w = GetSystemMetrics(SM_CXSCREEN);
4271 ok(w == 800, "Got unexpected screen width %u.\n", w);
4272 h = GetSystemMetrics(SM_CYSCREEN);
4273 ok(h == 600, "Got unexpected screen height %u.\n", h);
4275 ddraw2 = create_ddraw();
4276 hr = set_display_mode(ddraw2, 640, 480);
4277 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4278 w = GetSystemMetrics(SM_CXSCREEN);
4279 ok(w == 640, "Got unexpected screen width %u.\n", w);
4280 h = GetSystemMetrics(SM_CYSCREEN);
4281 ok(h == 480, "Got unexpected screen height %u.\n", h);
4283 hr = IDirectDraw4_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4284 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
4286 ref = IDirectDraw4_Release(ddraw1);
4287 ok(!ref, "Unexpected refcount %lu.\n", ref);
4288 w = GetSystemMetrics(SM_CXSCREEN);
4289 ok(w == 640, "Got unexpected screen width %u.\n", w);
4290 h = GetSystemMetrics(SM_CYSCREEN);
4291 ok(h == 480, "Got unexpected screen height %u.\n", h);
4293 ref = IDirectDraw4_Release(ddraw2);
4294 ok(!ref, "Unexpected refcount %lu.\n", ref);
4295 w = GetSystemMetrics(SM_CXSCREEN);
4296 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4297 h = GetSystemMetrics(SM_CYSCREEN);
4298 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4300 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
4301 ddraw1 = create_ddraw();
4302 hr = set_display_mode(ddraw1, 800, 600);
4303 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
4304 w = GetSystemMetrics(SM_CXSCREEN);
4305 ok(w == 800, "Got unexpected screen width %u.\n", w);
4306 h = GetSystemMetrics(SM_CYSCREEN);
4307 ok(h == 600, "Got unexpected screen height %u.\n", h);
4309 hr = IDirectDraw4_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4310 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
4312 ddraw2 = create_ddraw();
4313 hr = set_display_mode(ddraw2, 640, 480);
4314 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
4316 ref = IDirectDraw4_Release(ddraw1);
4317 ok(!ref, "Unexpected refcount %lu.\n", ref);
4318 w = GetSystemMetrics(SM_CXSCREEN);
4319 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4320 h = GetSystemMetrics(SM_CYSCREEN);
4321 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4323 ref = IDirectDraw4_Release(ddraw2);
4324 ok(!ref, "Unexpected refcount %lu.\n", ref);
4325 w = GetSystemMetrics(SM_CXSCREEN);
4326 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
4327 h = GetSystemMetrics(SM_CYSCREEN);
4328 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
4330 if (display_count < 2)
4332 skip("Following tests require two monitors.\n");
4333 goto done;
4336 ret = restore_display_modes(original_modes, display_count);
4337 ok(ret, "Failed to restore display modes.\n");
4339 second_monitor_name[0] = '\0';
4340 for (display_idx = 0; display_idx < display_count; ++display_idx)
4342 if (original_modes[display_idx].dmPosition.x || original_modes[display_idx].dmPosition.y)
4344 lstrcpyW(second_monitor_name, original_modes[display_idx].dmDeviceName);
4345 break;
4348 ok(lstrlenW(second_monitor_name), "Got an empty second monitor name.\n");
4349 memset(&old_devmode, 0, sizeof(old_devmode));
4350 old_devmode.dmSize = sizeof(old_devmode);
4351 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
4352 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4354 devmode = old_devmode;
4355 while (EnumDisplaySettingsW(second_monitor_name, mode_idx++, &devmode))
4357 if (devmode.dmPelsWidth != old_devmode.dmPelsWidth
4358 || devmode.dmPelsHeight != old_devmode.dmPelsHeight)
4359 break;
4361 ok(devmode.dmPelsWidth != old_devmode.dmPelsWidth
4362 || devmode.dmPelsHeight != old_devmode.dmPelsHeight,
4363 "Failed to find a different mode for the second monitor.\n");
4365 /* Test that no mode restorations for non-primary monitors if SetDisplayMode() was not called */
4366 ddraw1 = create_ddraw();
4367 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4368 hr = IDirectDraw4_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4369 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
4371 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4372 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4374 memset(&devmode2, 0, sizeof(devmode2));
4375 devmode2.dmSize = sizeof(devmode2);
4376 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4377 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4378 if (compare_mode_rect(&devmode2, &old_devmode))
4380 skip("Failed to change display settings of the second monitor.\n");
4381 ref = IDirectDraw4_Release(ddraw1);
4382 ok(!ref, "Unexpected refcount %lu.\n", ref);
4383 goto done;
4386 hr = IDirectDraw4_SetCooperativeLevel(ddraw1, window, DDSCL_NORMAL);
4387 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
4388 ref = IDirectDraw4_Release(ddraw1);
4389 ok(!ref, "Unexpected refcount %lu.\n", ref);
4391 memset(&devmode3, 0, sizeof(devmode3));
4392 devmode3.dmSize = sizeof(devmode3);
4393 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode3);
4394 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4395 ok(compare_mode_rect(&devmode3, &devmode2), "Got a different mode.\n");
4396 ret = restore_display_modes(original_modes, display_count);
4397 ok(ret, "Failed to restore display modes.\n");
4399 /* Test that mode restorations happen for non-primary monitors on ddraw releases if
4400 * SetDisplayMode() was called */
4401 ddraw1 = create_ddraw();
4402 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4403 hr = set_display_mode(ddraw1, 800, 600);
4404 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4406 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4407 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4409 ref = IDirectDraw4_Release(ddraw1);
4410 ok(!ref, "Unexpected refcount %lu.\n", ref);
4412 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4413 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4414 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4415 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4416 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4417 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4418 ret = restore_display_modes(original_modes, display_count);
4419 ok(ret, "Failed to restore display modes.\n");
4421 /* Test that mode restorations happen for non-primary monitors as well */
4422 ddraw1 = create_ddraw();
4423 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4424 hr = set_display_mode(ddraw1, 800, 600);
4425 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4427 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4428 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4430 hr = IDirectDraw4_RestoreDisplayMode(ddraw1);
4431 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#lx.\n", hr);
4433 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4434 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4435 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4436 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4437 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4438 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4440 ref = IDirectDraw4_Release(ddraw1);
4441 ok(!ref, "Unexpected refcount %lu.\n", ref);
4442 ret = restore_display_modes(original_modes, display_count);
4443 ok(ret, "Failed to restore display modes.\n");
4445 /* Test that mode restorations for non-primary monitors use display settings in the registry */
4446 ddraw1 = create_ddraw();
4447 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4448 hr = set_display_mode(ddraw1, 800, 600);
4449 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4451 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
4452 CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
4453 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4455 ref = IDirectDraw4_Release(ddraw1);
4456 ok(!ref, "Unexpected refcount %lu.\n", ref);
4458 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4459 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4460 ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
4461 "Expected resolution %lux%lu, got %lux%lu.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
4462 devmode2.dmPelsWidth, devmode2.dmPelsHeight);
4463 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4464 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4465 ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
4466 "Expected resolution %lux%lu, got %lux%lu.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
4467 devmode2.dmPelsWidth, devmode2.dmPelsHeight);
4468 ret = restore_display_modes(original_modes, display_count);
4469 ok(ret, "Failed to restore display modes.\n");
4471 /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
4472 * objects and one of them restores display mode */
4473 ddraw1 = create_ddraw();
4474 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4475 ddraw2 = create_ddraw();
4476 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4477 hr = set_display_mode(ddraw1, 800, 600);
4478 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4479 hr = set_display_mode(ddraw2, 640, 480);
4480 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4482 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4483 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4485 hr = IDirectDraw4_RestoreDisplayMode(ddraw2);
4486 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#lx.\n", hr);
4488 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4489 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4490 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4491 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4492 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4493 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4495 ref = IDirectDraw4_Release(ddraw2);
4496 ok(!ref, "Unexpected refcount %lu.\n", ref);
4497 ref = IDirectDraw4_Release(ddraw1);
4498 ok(!ref, "Unexpected refcount %lu.\n", ref);
4499 ret = restore_display_modes(original_modes, display_count);
4500 ok(ret, "Failed to restore display modes.\n");
4502 /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
4503 * objects and one of them got released */
4504 ddraw1 = create_ddraw();
4505 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4506 ddraw2 = create_ddraw();
4507 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4508 hr = set_display_mode(ddraw1, 800, 600);
4509 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4510 hr = set_display_mode(ddraw2, 640, 480);
4511 ok(hr == DD_OK, "Failed to set display mode, hr %#lx.\n", hr);
4513 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4514 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4516 ref = IDirectDraw4_Release(ddraw2);
4517 ok(!ref, "Unexpected refcount %lu.\n", ref);
4519 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4520 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4521 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4522 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4523 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
4524 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4526 ref = IDirectDraw4_Release(ddraw1);
4527 ok(!ref, "Unexpected refcount %lu.\n", ref);
4529 done:
4530 DestroyWindow(window);
4531 ret = restore_display_modes(original_modes, display_count);
4532 ok(ret, "Failed to restore display modes.\n");
4533 heap_free(original_modes);
4536 static void test_initialize(void)
4538 IDirectDraw4 *ddraw;
4539 HRESULT hr;
4541 ddraw = create_ddraw();
4542 ok(!!ddraw, "Failed to create a ddraw object.\n");
4544 hr = IDirectDraw4_Initialize(ddraw, NULL);
4545 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#lx.\n", hr);
4546 IDirectDraw4_Release(ddraw);
4548 CoInitialize(NULL);
4549 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw4, (void **)&ddraw);
4550 ok(SUCCEEDED(hr), "Failed to create IDirectDraw4 instance, hr %#lx.\n", hr);
4551 hr = IDirectDraw4_Initialize(ddraw, NULL);
4552 ok(hr == DD_OK, "Initialize returned hr %#lx, expected DD_OK.\n", hr);
4553 hr = IDirectDraw4_Initialize(ddraw, NULL);
4554 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#lx, expected DDERR_ALREADYINITIALIZED.\n", hr);
4555 IDirectDraw4_Release(ddraw);
4556 CoUninitialize();
4559 static void test_coop_level_surf_create(void)
4561 IDirectDrawSurface4 *surface;
4562 IDirectDraw4 *ddraw;
4563 DDSURFACEDESC2 ddsd;
4564 HRESULT hr;
4566 ddraw = create_ddraw();
4567 ok(!!ddraw, "Failed to create a ddraw object.\n");
4569 memset(&ddsd, 0, sizeof(ddsd));
4570 ddsd.dwSize = sizeof(ddsd);
4571 ddsd.dwFlags = DDSD_CAPS;
4572 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4573 surface = (void *)0xdeadbeef;
4574 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
4575 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#lx.\n", hr);
4576 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4578 surface = (void *)0xdeadbeef;
4579 hr = IDirectDraw4_CreateSurface(ddraw, NULL, &surface, NULL);
4580 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#lx.\n", hr);
4581 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4583 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4584 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4586 surface = (void *)0xdeadbeef;
4587 hr = IDirectDraw4_CreateSurface(ddraw, NULL, &surface, NULL);
4588 ok(hr == DDERR_INVALIDPARAMS, "Unexpected hr %#lx.\n", hr);
4589 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4591 IDirectDraw4_Release(ddraw);
4594 static void test_vb_discard(void)
4596 static const struct vec4 quad[] =
4598 { 0.0f, 480.0f, 0.0f, 1.0f},
4599 { 0.0f, 0.0f, 0.0f, 1.0f},
4600 {640.0f, 480.0f, 0.0f, 1.0f},
4601 {640.0f, 0.0f, 0.0f, 1.0f},
4604 IDirect3DDevice3 *device;
4605 IDirect3D3 *d3d;
4606 IDirect3DVertexBuffer *buffer;
4607 HWND window;
4608 HRESULT hr;
4609 D3DVERTEXBUFFERDESC desc;
4610 BYTE *data;
4611 static const unsigned int vbsize = 16;
4612 unsigned int i;
4614 window = create_window();
4615 if (!(device = create_device(window, DDSCL_NORMAL)))
4617 skip("Failed to create a 3D device, skipping test.\n");
4618 DestroyWindow(window);
4619 return;
4622 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
4623 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
4625 memset(&desc, 0, sizeof(desc));
4626 desc.dwSize = sizeof(desc);
4627 desc.dwCaps = D3DVBCAPS_WRITEONLY;
4628 desc.dwFVF = D3DFVF_XYZRHW;
4629 desc.dwNumVertices = vbsize;
4630 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &buffer, 0, NULL);
4631 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#lx.\n", hr);
4633 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
4634 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#lx.\n", hr);
4635 memcpy(data, quad, sizeof(quad));
4636 hr = IDirect3DVertexBuffer_Unlock(buffer);
4637 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#lx.\n", hr);
4639 hr = IDirect3DDevice3_BeginScene(device);
4640 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
4641 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
4642 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
4643 hr = IDirect3DDevice3_EndScene(device);
4644 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
4646 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
4647 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#lx.\n", hr);
4648 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
4649 hr = IDirect3DVertexBuffer_Unlock(buffer);
4650 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#lx.\n", hr);
4652 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
4653 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#lx.\n", hr);
4654 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
4656 if (data[i] != 0xaa)
4658 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
4659 break;
4662 hr = IDirect3DVertexBuffer_Unlock(buffer);
4663 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#lx.\n", hr);
4665 IDirect3DVertexBuffer_Release(buffer);
4666 IDirect3D3_Release(d3d);
4667 IDirect3DDevice3_Release(device);
4668 DestroyWindow(window);
4671 static void test_coop_level_multi_window(void)
4673 HWND window1, window2;
4674 IDirectDraw4 *ddraw;
4675 HRESULT hr;
4677 window1 = create_window();
4678 window2 = create_window();
4679 ddraw = create_ddraw();
4680 ok(!!ddraw, "Failed to create a ddraw object.\n");
4682 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
4683 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4684 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
4685 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
4686 ok(IsWindow(window1), "Window 1 was destroyed.\n");
4687 ok(IsWindow(window2), "Window 2 was destroyed.\n");
4689 IDirectDraw4_Release(ddraw);
4690 DestroyWindow(window2);
4691 DestroyWindow(window1);
4694 static void test_draw_strided(void)
4696 static struct vec3 position[] =
4698 {-1.0, -1.0, 0.0},
4699 {-1.0, 1.0, 0.0},
4700 { 1.0, 1.0, 0.0},
4701 { 1.0, -1.0, 0.0},
4703 static DWORD diffuse[] =
4705 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
4707 static WORD indices[] =
4709 0, 1, 2, 2, 3, 0
4712 IDirectDrawSurface4 *rt;
4713 IDirect3DDevice3 *device;
4714 unsigned int color;
4715 HWND window;
4716 HRESULT hr;
4717 D3DDRAWPRIMITIVESTRIDEDDATA strided;
4718 IDirect3DViewport3 *viewport;
4719 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4721 window = create_window();
4722 if (!(device = create_device(window, DDSCL_NORMAL)))
4724 skip("Failed to create a 3D device, skipping test.\n");
4725 DestroyWindow(window);
4726 return;
4729 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
4730 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
4731 viewport = create_viewport(device, 0, 0, 640, 480);
4732 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
4733 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#lx.\n", hr);
4734 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
4735 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#lx.\n", hr);
4737 hr = IDirect3DDevice3_BeginScene(device);
4738 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
4740 memset(&strided, 0x55, sizeof(strided));
4741 strided.position.lpvData = position;
4742 strided.position.dwStride = sizeof(*position);
4743 strided.diffuse.lpvData = diffuse;
4744 strided.diffuse.dwStride = sizeof(*diffuse);
4745 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
4746 &strided, 4, indices, 6, 0);
4747 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
4749 hr = IDirect3DDevice3_EndScene(device);
4750 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
4752 color = get_surface_color(rt, 320, 240);
4753 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
4755 IDirect3DViewport3_Release(viewport);
4756 IDirectDrawSurface4_Release(rt);
4757 IDirect3DDevice3_Release(device);
4758 DestroyWindow(window);
4761 static void test_lighting(void)
4763 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
4764 static D3DMATRIX mat =
4766 1.0f, 0.0f, 0.0f, 0.0f,
4767 0.0f, 1.0f, 0.0f, 0.0f,
4768 0.0f, 0.0f, 1.0f, 0.0f,
4769 0.0f, 0.0f, 0.0f, 1.0f,
4771 mat_singular =
4773 1.0f, 0.0f, 1.0f, 0.0f,
4774 0.0f, 1.0f, 0.0f, 0.0f,
4775 1.0f, 0.0f, 1.0f, 0.0f,
4776 0.0f, 0.0f, 0.5f, 1.0f,
4778 mat_transf =
4780 0.0f, 0.0f, 1.0f, 0.0f,
4781 0.0f, 1.0f, 0.0f, 0.0f,
4782 -1.0f, 0.0f, 0.0f, 0.0f,
4783 10.f, 10.0f, 10.0f, 1.0f,
4785 mat_nonaffine =
4787 1.0f, 0.0f, 0.0f, 0.0f,
4788 0.0f, 1.0f, 0.0f, 0.0f,
4789 0.0f, 0.0f, 1.0f, -1.0f,
4790 10.f, 10.0f, 10.0f, 0.0f,
4792 static struct vertex
4794 struct vec3 position;
4795 DWORD diffuse;
4797 unlitquad[] =
4799 {{-1.0f, -1.0f, 0.1f}, 0xffff0000},
4800 {{-1.0f, 0.0f, 0.1f}, 0xffff0000},
4801 {{ 0.0f, 0.0f, 0.1f}, 0xffff0000},
4802 {{ 0.0f, -1.0f, 0.1f}, 0xffff0000},
4804 litquad[] =
4806 {{-1.0f, 0.0f, 0.1f}, 0xff00ff00},
4807 {{-1.0f, 1.0f, 0.1f}, 0xff00ff00},
4808 {{ 0.0f, 1.0f, 0.1f}, 0xff00ff00},
4809 {{ 0.0f, 0.0f, 0.1f}, 0xff00ff00},
4811 static struct vertex_normal
4813 struct vec3 position;
4814 struct vec3 normal;
4815 DWORD diffuse;
4817 unlitnquad[] =
4819 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4820 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4821 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4822 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4824 litnquad[] =
4826 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4827 {{0.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4828 {{1.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4829 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4831 nquad[] =
4833 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4834 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4835 {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4836 {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4838 rotatedquad[] =
4840 {{-10.0f, -11.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4841 {{-10.0f, -9.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4842 {{-10.0f, -9.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4843 {{-10.0f, -11.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4845 translatedquad[] =
4847 {{-11.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4848 {{-11.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4849 {{ -9.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4850 {{ -9.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4852 static WORD indices[] = {0, 1, 2, 2, 3, 0};
4853 static const struct
4855 D3DMATRIX *world_matrix;
4856 void *quad;
4857 DWORD expected;
4858 const char *message;
4860 tests[] =
4862 {&mat, nquad, 0x000080ff, "Lit quad with light"},
4863 {&mat_singular, nquad, 0x000080b4, "Lit quad with singular world matrix"},
4864 {&mat_transf, rotatedquad, 0x000080ff, "Lit quad with transformation matrix"},
4865 {&mat_nonaffine, translatedquad, 0x000080ff, "Lit quad with non-affine matrix"},
4867 DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
4868 IDirect3DVertexBuffer *src_vb1, *src_vb2, *dst_vb;
4869 IDirect3DViewport3 *viewport, *viewport2;
4870 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
4871 struct vertex_normal *src_data2;
4872 IDirect3DMaterial3 *material;
4873 D3DMATERIALHANDLE mat_handle;
4874 D3DVERTEXBUFFERDESC vb_desc;
4875 IDirect3DDevice3 *device;
4876 struct vertex *src_data1;
4877 IDirectDrawSurface4 *rt;
4878 IDirect3DLight *light;
4879 unsigned int color, i;
4880 D3DLIGHT2 light_desc;
4881 IDirect3D3 *d3d;
4882 ULONG refcount;
4883 HWND window;
4884 HRESULT hr;
4885 struct
4887 struct vec4 position;
4888 unsigned int diffuse, specular;
4890 *dst_data;
4892 window = create_window();
4893 if (!(device = create_device(window, DDSCL_NORMAL)))
4895 skip("Failed to create a 3D device, skipping test.\n");
4896 DestroyWindow(window);
4897 return;
4900 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
4901 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4903 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
4904 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4906 viewport = create_viewport(device, 0, 0, 640, 480);
4907 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
4908 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4910 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
4911 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4913 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
4914 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4915 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
4916 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4917 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
4918 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4919 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
4920 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4921 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4922 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4923 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
4924 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4925 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
4926 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4928 hr = IDirect3DDevice3_BeginScene(device);
4929 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4931 memset(&vb_desc, 0, sizeof(vb_desc));
4932 vb_desc.dwSize = sizeof(vb_desc);
4933 vb_desc.dwFVF = fvf;
4934 vb_desc.dwNumVertices = 2;
4935 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &src_vb1, 0, NULL);
4936 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4937 vb_desc.dwSize = sizeof(vb_desc);
4938 vb_desc.dwFVF = nfvf;
4939 vb_desc.dwNumVertices = 2;
4940 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &src_vb2, 0, NULL);
4941 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4943 memset(&vb_desc, 0, sizeof(vb_desc));
4944 vb_desc.dwSize = sizeof(vb_desc);
4945 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
4946 vb_desc.dwNumVertices = 4;
4947 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0, NULL);
4948 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4950 hr = IDirect3DVertexBuffer_Lock(src_vb1, 0, (void **)&src_data1, NULL);
4951 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4952 memcpy(src_data1, unlitquad, sizeof(*src_data1));
4953 memcpy(&src_data1[1], litquad, sizeof(*src_data1));
4954 hr = IDirect3DVertexBuffer_Unlock(src_vb1);
4955 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4957 hr = IDirect3DVertexBuffer_Lock(src_vb2, 0, (void **)&src_data2, NULL);
4958 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4959 memcpy(src_data2, unlitnquad, sizeof(*src_data2));
4960 memcpy(&src_data2[1], litnquad, sizeof(*src_data2));
4961 hr = IDirect3DVertexBuffer_Unlock(src_vb2);
4962 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4964 /* There is no D3DRENDERSTATE_LIGHTING on ddraw < 7. */
4965 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4966 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4967 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0,
4968 1, src_vb1, 0, device, 0);
4969 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4970 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4,
4971 indices, 6, 0);
4972 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4974 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
4975 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4976 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 1,
4977 1, src_vb1, 1, device, 0);
4978 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4979 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4,
4980 indices, 6, 0);
4981 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4983 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4984 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4985 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 2,
4986 1, src_vb2, 0, device, 0);
4987 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4988 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4,
4989 indices, 6, 0);
4990 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4992 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
4993 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4994 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 3,
4995 1, src_vb2, 1, device, 0);
4996 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4997 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4,
4998 indices, 6, 0);
4999 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5001 hr = IDirect3DDevice3_EndScene(device);
5002 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5004 hr = IDirect3DVertexBuffer_Lock(dst_vb, 0, (void **)&dst_data, NULL);
5005 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5007 color = get_surface_color(rt, 160, 360);
5008 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
5009 ok(dst_data[0].diffuse == 0xffff0000,
5010 "Unlit quad without normals has color 0x%08x, expected 0xffff0000.\n", dst_data[0].diffuse);
5011 ok(!dst_data[0].specular,
5012 "Unexpected specular color 0x%08x.\n", dst_data[0].specular);
5014 color = get_surface_color(rt, 160, 120);
5015 ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
5016 ok(dst_data[1].diffuse == 0xff00ff00,
5017 "Lit quad without normals has color 0x%08x, expected 0xff000000.\n", dst_data[1].diffuse);
5018 ok(!dst_data[1].specular,
5019 "Unexpected specular color 0x%08x.\n", dst_data[1].specular);
5021 color = get_surface_color(rt, 480, 360);
5022 ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x.\n", color);
5023 ok(dst_data[2].diffuse == 0xff0000ff,
5024 "Unlit quad with normals has color 0x%08x, expected 0xff0000ff.\n", dst_data[2].diffuse);
5025 ok(!dst_data[2].specular,
5026 "Unexpected specular color 0x%08x.\n", dst_data[2].specular);
5028 color = get_surface_color(rt, 480, 120);
5029 ok(color == 0x00ffff00, "Lit quad with normals has color 0x%08x.\n", color);
5030 ok(dst_data[3].diffuse == 0xffffff00,
5031 "Lit quad with normals has color 0x%08x, expected 0xff000000.\n", dst_data[3].diffuse);
5032 ok(!dst_data[3].specular,
5033 "Unexpected specular color 0x%08x.\n", dst_data[3].specular);
5035 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
5036 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5038 material = create_diffuse_and_ambient_material(device, 0.0f, 1.0f, 1.0f, 0.5f);
5039 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
5040 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5041 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
5042 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5043 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_AMBIENT, 0xff008000);
5044 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5046 hr = IDirect3D3_CreateLight(d3d, &light, NULL);
5047 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5048 memset(&light_desc, 0, sizeof(light_desc));
5049 light_desc.dwSize = sizeof(light_desc);
5050 light_desc.dltType = D3DLIGHT_DIRECTIONAL;
5051 U1(light_desc.dcvColor).r = 1.0f;
5052 U2(light_desc.dcvColor).g = 1.0f;
5053 U3(light_desc.dcvColor).b = 1.0f;
5054 U4(light_desc.dcvColor).a = 0.5f;
5055 U3(light_desc.dvDirection).z = 1.0f;
5056 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
5057 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5058 hr = IDirect3DViewport3_AddLight(viewport, light);
5059 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5060 hr = IDirect3DViewport3_AddLight(viewport, light);
5061 ok(hr == D3DERR_LIGHTHASVIEWPORT, "Got unexpected hr %#lx.\n", hr);
5063 viewport2 = create_viewport(device, 0, 0, 640, 480);
5064 hr = IDirect3DViewport3_AddLight(viewport2, light);
5065 ok(hr == D3DERR_LIGHTHASVIEWPORT, "Got unexpected hr %#lx.\n", hr);
5066 IDirect3DViewport3_Release(viewport2);
5068 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
5069 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5071 hr = IDirect3DDevice3_BeginScene(device);
5072 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5074 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, nquad,
5075 4, indices, 6, 0);
5076 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5078 hr = IDirect3DDevice3_EndScene(device);
5079 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5081 color = get_surface_color(rt, 320, 240);
5082 ok(color == 0x00008000, "Lit quad with no light has color 0x%08x.\n", color);
5084 light_desc.dwFlags = D3DLIGHT_ACTIVE;
5085 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
5086 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5087 hr = IDirect3DViewport3_DeleteLight(viewport, light);
5088 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5089 light_desc.dwFlags = 0;
5090 hr = IDirect3DLight_GetLight(light, (D3DLIGHT *)&light_desc);
5091 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5092 ok(light_desc.dwFlags == D3DLIGHT_ACTIVE, "Got unexpected flags %#lx.\n", light_desc.dwFlags);
5094 hr = IDirect3DViewport3_AddLight(viewport, light);
5095 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5097 for (i = 0; i < ARRAY_SIZE(tests); ++i)
5099 hr = IDirect3DVertexBuffer_Lock(src_vb2, 0, (void **)&src_data2, NULL);
5100 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5101 memcpy(src_data2, tests[i].quad, sizeof(*src_data2));
5102 hr = IDirect3DVertexBuffer_Unlock(src_vb2);
5103 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5105 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
5106 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5108 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
5109 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5111 hr = IDirect3DDevice3_BeginScene(device);
5112 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5114 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
5115 1, src_vb2, 0, device, 0);
5116 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5117 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, tests[i].quad,
5118 4, indices, 6, 0);
5119 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5121 hr = IDirect3DDevice3_EndScene(device);
5122 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5124 hr = IDirect3DVertexBuffer_Lock(dst_vb, 0, (void **)&dst_data, NULL);
5125 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5127 color = get_surface_color(rt, 320, 240);
5128 ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
5129 ok(dst_data[0].diffuse == (tests[i].expected | 0xff000000),
5130 "%s has color 0x%08x.\n", tests[i].message, dst_data[0].diffuse);
5131 ok(!dst_data[0].specular,
5132 "%s has specular color 0x%08x.\n", tests[i].message, dst_data[0].specular);
5134 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
5135 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5138 IDirect3DVertexBuffer_Release(src_vb1);
5139 IDirect3DVertexBuffer_Release(src_vb2);
5140 IDirect3DVertexBuffer_Release(dst_vb);
5142 hr = IDirect3DViewport3_DeleteLight(viewport, light);
5143 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5144 IDirect3DLight_Release(light);
5145 destroy_material(material);
5146 IDirect3DViewport3_Release(viewport);
5147 IDirectDrawSurface4_Release(rt);
5148 refcount = IDirect3DDevice3_Release(device);
5149 ok(!refcount, "Device has %lu references left.\n", refcount);
5150 IDirect3D3_Release(d3d);
5151 DestroyWindow(window);
5154 static void test_specular_lighting(void)
5156 static const unsigned int vertices_side = 5;
5157 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
5158 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
5159 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
5160 static D3DMATRIX mat =
5162 1.0f, 0.0f, 0.0f, 0.0f,
5163 0.0f, 1.0f, 0.0f, 0.0f,
5164 0.0f, 0.0f, 1.0f, 0.0f,
5165 0.0f, 0.0f, 0.0f, 1.0f,
5167 static const struct vertex
5169 struct vec3 position;
5170 struct vec3 normal;
5172 vertices[] =
5174 {{-0.5f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
5175 {{ 0.0f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
5176 {{ 0.5f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
5177 {{-0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
5178 {{ 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
5179 {{ 0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
5180 {{-0.5f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
5181 {{ 0.0f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
5182 {{ 0.5f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
5185 static D3DLIGHT2 directional =
5187 sizeof(D3DLIGHT2),
5188 D3DLIGHT_DIRECTIONAL,
5189 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
5190 {{0.0f}, {0.0f}, {0.0f}},
5191 {{0.0f}, {0.0f}, {1.0f}},
5193 point =
5195 sizeof(D3DLIGHT2),
5196 D3DLIGHT_POINT,
5197 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
5198 {{0.0f}, {0.0f}, {0.0f}},
5199 {{0.0f}, {0.0f}, {0.0f}},
5200 100.0f,
5201 0.0f,
5202 0.0f, 0.0f, 1.0f,
5204 spot =
5206 sizeof(D3DLIGHT2),
5207 D3DLIGHT_SPOT,
5208 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
5209 {{0.0f}, {0.0f}, {0.0f}},
5210 {{0.0f}, {0.0f}, {1.0f}},
5211 100.0f,
5212 1.0f,
5213 0.0f, 0.0f, 1.0f,
5214 M_PI / 12.0f, M_PI / 3.0f
5216 parallelpoint =
5218 sizeof(D3DLIGHT2),
5219 D3DLIGHT_PARALLELPOINT,
5220 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
5221 {{0.5f}, {0.0f}, {-1.0f}},
5222 {{0.0f}, {0.0f}, {0.0f}},
5224 point_side =
5226 sizeof(D3DLIGHT2),
5227 D3DLIGHT_POINT,
5228 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
5229 {{-1.1f}, {0.0f}, {1.1f}},
5230 {{0.0f}, {0.0f}, {0.0f}},
5231 100.0f,
5232 0.0f,
5233 1.0f, 0.0f, 0.0f,
5235 point_far =
5237 sizeof(D3DLIGHT2),
5238 D3DLIGHT_POINT,
5239 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
5240 {{0.0f}, {0.0f}, {0.1f}},
5241 {{0.0f}, {0.0f}, {0.0f}},
5242 1.0f,
5243 0.0f,
5244 1.0f, 0.0f, 0.0f,
5246 static const struct expected_color
5248 unsigned int x, y, color;
5250 expected_directional[] =
5252 {160, 120, 0x003c3c3c},
5253 {320, 120, 0x00717171},
5254 {480, 120, 0x003c3c3c},
5255 {160, 240, 0x00717171},
5256 {320, 240, 0x00ffffff},
5257 {480, 240, 0x00717171},
5258 {160, 360, 0x003c3c3c},
5259 {320, 360, 0x00717171},
5260 {480, 360, 0x003c3c3c},
5262 expected_point[] =
5264 {160, 120, 0x00000000},
5265 {320, 120, 0x00090909},
5266 {480, 120, 0x00000000},
5267 {160, 240, 0x00090909},
5268 {320, 240, 0x00fafafa},
5269 {480, 240, 0x00090909},
5270 {160, 360, 0x00000000},
5271 {320, 360, 0x00090909},
5272 {480, 360, 0x00000000},
5274 expected_spot[] =
5276 {160, 120, 0x00000000},
5277 {320, 120, 0x00020202},
5278 {480, 120, 0x00000000},
5279 {160, 240, 0x00020202},
5280 {320, 240, 0x00fafafa},
5281 {480, 240, 0x00020202},
5282 {160, 360, 0x00000000},
5283 {320, 360, 0x00020202},
5284 {480, 360, 0x00000000},
5286 expected_parallelpoint[] =
5288 {160, 120, 0x00050505},
5289 {320, 120, 0x002c2c2c},
5290 {480, 120, 0x006e6e6e},
5291 {160, 240, 0x00090909},
5292 {320, 240, 0x00717171},
5293 {480, 240, 0x00ffffff},
5294 {160, 360, 0x00050505},
5295 {320, 360, 0x002c2c2c},
5296 {480, 360, 0x006e6e6e},
5298 expected_point_far[] =
5300 {160, 120, 0x00000000},
5301 {320, 120, 0x00000000},
5302 {480, 120, 0x00000000},
5303 {160, 240, 0x00000000},
5304 {320, 240, 0x00ffffff},
5305 {480, 240, 0x00000000},
5306 {160, 360, 0x00000000},
5307 {320, 360, 0x00000000},
5308 {480, 360, 0x00000000},
5310 expected_zero[] =
5312 {160, 120, 0x00000000},
5313 {320, 120, 0x00000000},
5314 {480, 120, 0x00000000},
5315 {160, 240, 0x00000000},
5316 {320, 240, 0x00000000},
5317 {480, 240, 0x00000000},
5318 {160, 360, 0x00000000},
5319 {320, 360, 0x00000000},
5320 {480, 360, 0x00000000},
5322 static const struct
5324 D3DLIGHT2 *light;
5325 BOOL local_viewer;
5326 float specular_power;
5327 const struct expected_color *expected;
5328 unsigned int expected_count;
5330 tests[] =
5332 /* D3DRENDERSTATE_LOCALVIEWER does not exist in D3D < 7 (the behavior is
5333 * the one you get on newer D3D versions with it set as TRUE). */
5334 {&directional, FALSE, 30.0f, expected_directional, ARRAY_SIZE(expected_directional)},
5335 {&directional, TRUE, 30.0f, expected_directional, ARRAY_SIZE(expected_directional)},
5336 {&point, TRUE, 30.0f, expected_point, ARRAY_SIZE(expected_point)},
5337 {&spot, TRUE, 30.0f, expected_spot, ARRAY_SIZE(expected_spot)},
5338 {&parallelpoint, TRUE, 30.0f, expected_parallelpoint, ARRAY_SIZE(expected_parallelpoint)},
5339 {&point_side, TRUE, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
5340 {&point_far, TRUE, 1.0f, expected_point_far, ARRAY_SIZE(expected_point_far)},
5341 {&directional, FALSE, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
5342 {&directional, TRUE, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
5343 {&point, TRUE, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
5344 {&spot, TRUE, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
5345 {&parallelpoint, TRUE, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
5346 {&point_far, TRUE, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)},
5349 IDirect3DLight *light, *dummy_lights[64];
5350 IDirect3DVertexBuffer *src_vb, *dst_vb;
5351 struct vertex *quad, *src_data;
5352 unsigned int color, i, j, x, y;
5353 D3DVERTEXBUFFERDESC vb_desc;
5354 D3DMATERIALHANDLE mat_handle;
5355 IDirect3DViewport3 *viewport;
5356 IDirect3DMaterial3 *material;
5357 IDirect3DDevice3 *device;
5358 IDirectDrawSurface4 *rt;
5359 D3DLIGHT2 light_desc;
5360 IDirect3D3 *d3d;
5361 ULONG refcount;
5362 HWND window;
5363 HRESULT hr;
5364 struct
5366 struct vec4 position;
5367 unsigned int diffuse, specular;
5368 } *dst_data;
5369 WORD *indices;
5371 window = create_window();
5372 if (!(device = create_device(window, DDSCL_NORMAL)))
5374 skip("Failed to create a 3D device, skipping test.\n");
5375 DestroyWindow(window);
5376 return;
5379 quad = heap_alloc(vertices_side * vertices_side * sizeof(*quad));
5380 indices = heap_alloc(indices_count * sizeof(*indices));
5381 for (i = 0, y = 0; y < vertices_side; ++y)
5383 for (x = 0; x < vertices_side; ++x)
5385 quad[i].position.x = x * 2.0f / (vertices_side - 1) - 1.0f;
5386 quad[i].position.y = y * 2.0f / (vertices_side - 1) - 1.0f;
5387 quad[i].position.z = 1.0f;
5388 quad[i].normal.x = 0.0f;
5389 quad[i].normal.y = 0.0f;
5390 quad[i++].normal.z = -1.0f;
5393 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
5395 for (x = 0; x < (vertices_side - 1); ++x)
5397 indices[i++] = y * vertices_side + x + 1;
5398 indices[i++] = y * vertices_side + x;
5399 indices[i++] = (y + 1) * vertices_side + x;
5400 indices[i++] = y * vertices_side + x + 1;
5401 indices[i++] = (y + 1) * vertices_side + x;
5402 indices[i++] = (y + 1) * vertices_side + x + 1;
5406 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
5407 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5409 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
5410 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5412 viewport = create_viewport(device, 0, 0, 640, 480);
5413 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
5414 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5416 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
5417 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5418 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
5419 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5420 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
5421 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5422 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
5423 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5424 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
5425 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5427 memset(&light_desc, 0, sizeof(light_desc));
5428 light_desc.dwSize = sizeof(light_desc);
5429 light_desc.dltType = D3DLIGHT_DIRECTIONAL;
5430 light_desc.dwFlags = D3DLIGHT_ACTIVE;
5431 U3(light_desc.dvDirection).z = 1.0f;
5433 for (i = 0; i < ARRAY_SIZE(dummy_lights); ++i)
5435 hr = IDirect3D3_CreateLight(d3d, &dummy_lights[i], NULL);
5436 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5437 hr = IDirect3DViewport3_AddLight(viewport, dummy_lights[i]);
5438 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5439 hr = IDirect3DLight_SetLight(dummy_lights[i], (D3DLIGHT *)&light_desc);
5440 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5443 hr = IDirect3D3_CreateLight(d3d, &light, NULL);
5444 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5445 hr = IDirect3DViewport3_AddLight(viewport, light);
5446 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5448 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
5449 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5451 memset(&vb_desc, 0, sizeof(vb_desc));
5452 vb_desc.dwSize = sizeof(vb_desc);
5453 vb_desc.dwFVF = fvf;
5454 vb_desc.dwNumVertices = ARRAY_SIZE(vertices);
5455 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &src_vb, 0, NULL);
5456 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5457 hr = IDirect3DVertexBuffer_Lock(src_vb, 0, (void **)&src_data, NULL);
5458 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5459 memcpy(src_data, vertices, sizeof(vertices));
5460 hr = IDirect3DVertexBuffer_Unlock(src_vb);
5461 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5463 memset(&vb_desc, 0, sizeof(vb_desc));
5464 vb_desc.dwSize = sizeof(vb_desc);
5465 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
5466 vb_desc.dwNumVertices = ARRAY_SIZE(vertices);
5467 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0, NULL);
5468 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5470 for (i = 0; i < ARRAY_SIZE(tests); ++i)
5472 tests[i].light->dwFlags = D3DLIGHT_ACTIVE;
5473 hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)tests[i].light);
5474 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5476 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
5477 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5479 material = create_specular_material(device, 1.0f, 1.0f, 1.0f, 0.5f, tests[i].specular_power);
5480 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
5481 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5482 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
5483 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5485 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
5486 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5488 hr = IDirect3DDevice3_BeginScene(device);
5489 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5491 hr = IDirect3DVertexBuffer_Lock(dst_vb, 0, (void **)&dst_data, NULL);
5492 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5493 memset(dst_data, 0, sizeof(*dst_data) * ARRAY_SIZE(vertices));
5494 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
5495 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5497 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
5498 ARRAY_SIZE(vertices), src_vb, 0, device, 0);
5499 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5500 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, quad,
5501 vertices_side * vertices_side, indices, indices_count, 0);
5502 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5504 hr = IDirect3DDevice3_EndScene(device);
5505 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5507 hr = IDirect3DVertexBuffer_Lock(dst_vb, 0, (void **)&dst_data, NULL);
5508 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5510 for (j = 0; j < tests[i].expected_count; ++j)
5512 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
5513 ok(compare_color(color, tests[i].expected[j].color, 1),
5514 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
5515 tests[i].expected[j].color, tests[i].expected[j].x,
5516 tests[i].expected[j].y, color, i);
5517 ok(!dst_data[j].diffuse, "Expected color 0x00000000 for vertex %u, got 0x%08x, case %u.\n",
5518 j, dst_data[j].diffuse, i);
5519 ok(compare_color(dst_data[j].specular, tests[i].expected[j].color, 1),
5520 "Expected color 0x%08x for vertex %u, got 0x%08x, case %u.\n",
5521 tests[i].expected[j].color, j, dst_data[j].specular, i);
5523 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
5524 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5526 destroy_material(material);
5529 for (i = 0; i < ARRAY_SIZE(dummy_lights); ++i)
5530 IDirect3DLight_Release(dummy_lights[i]);
5532 IDirect3DVertexBuffer_Release(dst_vb);
5533 IDirect3DVertexBuffer_Release(src_vb);
5535 hr = IDirect3DViewport3_DeleteLight(viewport, light);
5536 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5537 IDirect3DLight_Release(light);
5538 IDirect3DViewport3_Release(viewport);
5539 IDirectDrawSurface4_Release(rt);
5540 refcount = IDirect3DDevice3_Release(device);
5541 ok(!refcount, "Device has %lu references left.\n", refcount);
5542 IDirect3D3_Release(d3d);
5543 DestroyWindow(window);
5544 heap_free(indices);
5545 heap_free(quad);
5548 static void test_clear_rect_count(void)
5550 IDirectDrawSurface4 *rt;
5551 IDirect3DDevice3 *device;
5552 unsigned int color;
5553 HWND window;
5554 HRESULT hr;
5555 IDirect3DViewport3 *viewport;
5556 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
5558 window = create_window();
5559 if (!(device = create_device(window, DDSCL_NORMAL)))
5561 skip("Failed to create a 3D device, skipping test.\n");
5562 DestroyWindow(window);
5563 return;
5566 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
5567 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
5569 viewport = create_viewport(device, 0, 0, 640, 480);
5570 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
5571 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#lx.\n", hr);
5572 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00ffffff, 0.0f, 0);
5573 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#lx.\n", hr);
5574 hr = IDirect3DViewport3_Clear2(viewport, 0, &clear_rect, D3DCLEAR_TARGET, 0x00ff0000, 0.0f, 0);
5575 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#lx.\n", hr);
5576 hr = IDirect3DViewport3_Clear2(viewport, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 0.0f, 0);
5577 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#lx.\n", hr);
5578 hr = IDirect3DViewport3_Clear2(viewport, 1, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
5579 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#lx.\n", hr);
5581 color = get_surface_color(rt, 320, 240);
5582 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x000000ff, 1)),
5583 "Got unexpected color 0x%08x.\n", color);
5585 IDirect3DViewport3_Release(viewport);
5586 IDirectDrawSurface4_Release(rt);
5587 IDirect3DDevice3_Release(device);
5588 DestroyWindow(window);
5591 static BOOL test_mode_restored(IDirectDraw4 *ddraw, HWND window)
5593 DDSURFACEDESC2 ddsd1, ddsd2;
5594 HRESULT hr;
5596 memset(&ddsd1, 0, sizeof(ddsd1));
5597 ddsd1.dwSize = sizeof(ddsd1);
5598 hr = IDirectDraw4_GetDisplayMode(ddraw, &ddsd1);
5599 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#lx.\n", hr);
5601 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5602 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
5603 hr = set_display_mode(ddraw, 640, 480);
5604 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
5605 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5606 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
5608 memset(&ddsd2, 0, sizeof(ddsd2));
5609 ddsd2.dwSize = sizeof(ddsd2);
5610 hr = IDirectDraw4_GetDisplayMode(ddraw, &ddsd2);
5611 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#lx.\n", hr);
5612 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
5613 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#lx.\n", hr);
5615 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
5618 static void test_coop_level_versions(void)
5620 HWND window;
5621 IDirectDraw *ddraw;
5622 HRESULT hr;
5623 BOOL restored;
5624 IDirectDrawSurface *surface;
5625 IDirectDraw4 *ddraw4;
5626 DDSURFACEDESC ddsd;
5628 window = create_window();
5629 ddraw4 = create_ddraw();
5630 ok(!!ddraw4, "Failed to create a ddraw object.\n");
5631 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
5632 restored = test_mode_restored(ddraw4, window);
5633 ok(restored, "Display mode not restored in new ddraw object\n");
5635 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
5636 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
5637 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#lx.\n", hr);
5639 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
5640 ok(FAILED(hr), "SetCooperativeLevel returned %#lx, expected failure.\n", hr);
5641 restored = test_mode_restored(ddraw4, window);
5642 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
5644 /* A successful one does */
5645 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5646 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
5647 restored = test_mode_restored(ddraw4, window);
5648 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
5650 IDirectDraw_Release(ddraw);
5651 IDirectDraw4_Release(ddraw4);
5653 ddraw4 = create_ddraw();
5654 ok(!!ddraw4, "Failed to create a ddraw object.\n");
5655 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
5656 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#lx.\n", hr);
5658 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
5659 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
5660 restored = test_mode_restored(ddraw4, window);
5661 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
5663 IDirectDraw_Release(ddraw);
5664 IDirectDraw4_Release(ddraw4);
5666 /* A failing call does not restore the ddraw2+ behavior */
5667 ddraw4 = create_ddraw();
5668 ok(!!ddraw4, "Failed to create a ddraw object.\n");
5669 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
5670 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#lx.\n", hr);
5672 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5673 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
5674 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
5675 ok(FAILED(hr), "SetCooperativeLevel returned %#lx, expected failure.\n", hr);
5676 restored = test_mode_restored(ddraw4, window);
5677 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
5679 IDirectDraw_Release(ddraw);
5680 IDirectDraw4_Release(ddraw4);
5682 /* Neither does a sequence of successful calls with the new interface */
5683 ddraw4 = create_ddraw();
5684 ok(!!ddraw4, "Failed to create a ddraw object.\n");
5685 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
5686 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#lx.\n", hr);
5688 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5689 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
5690 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
5691 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
5692 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_NORMAL);
5693 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
5695 restored = test_mode_restored(ddraw4, window);
5696 ok(!restored, "Display mode restored after ddraw1-ddraw4 SetCooperativeLevel() call sequence\n");
5697 IDirectDraw_Release(ddraw);
5698 IDirectDraw4_Release(ddraw4);
5700 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
5701 ddraw4 = create_ddraw();
5702 ok(!!ddraw4, "Failed to create a ddraw object.\n");
5703 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirectDraw, (void **)&ddraw);
5704 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#lx.\n", hr);
5706 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, DDSCL_NORMAL);
5707 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#lx.\n", hr);
5709 memset(&ddsd, 0, sizeof(ddsd));
5710 ddsd.dwSize = sizeof(ddsd);
5711 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5712 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5713 ddsd.dwWidth = ddsd.dwHeight = 8;
5714 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
5715 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#lx.\n", hr);
5716 IDirectDrawSurface_Release(surface);
5717 restored = test_mode_restored(ddraw4, window);
5718 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
5720 IDirectDraw_Release(ddraw);
5721 IDirectDraw4_Release(ddraw4);
5722 DestroyWindow(window);
5725 static void test_lighting_interface_versions(void)
5727 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
5728 IDirect3DMaterial3 *emissive;
5729 IDirect3DViewport3 *viewport;
5730 IDirect3DDevice3 *device;
5731 IDirectDrawSurface4 *rt;
5732 unsigned int color, i;
5733 HWND window;
5734 HRESULT hr;
5735 D3DMATERIALHANDLE mat_handle;
5736 DWORD rs;
5737 ULONG ref;
5738 static D3DVERTEX quad[] =
5740 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5741 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5742 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5743 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5746 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
5747 static struct
5749 struct vec3 position;
5750 struct vec3 normal;
5751 DWORD diffuse, specular;
5753 quad2[] =
5755 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
5756 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
5757 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
5758 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
5761 static D3DLVERTEX lquad[] =
5763 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
5764 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
5765 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
5766 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
5769 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
5770 static struct
5772 struct vec3 position;
5773 DWORD diffuse, specular;
5774 struct vec2 texcoord;
5776 lquad2[] =
5778 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
5779 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
5780 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
5781 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
5784 static D3DTLVERTEX tlquad[] =
5786 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5787 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5788 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5789 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5792 static const struct
5794 DWORD vertextype;
5795 void *data;
5796 DWORD d3drs_lighting, d3drs_specular;
5797 DWORD draw_flags;
5798 unsigned int color;
5800 tests[] =
5802 /* Lighting is enabled when all of these conditions are met:
5803 * 1) No pretransformed position(D3DFVF_XYZRHW)
5804 * 2) Normals are available (D3DFVF_NORMAL)
5805 * 3) D3DDP_DONOTLIGHT is not set.
5807 * D3DRENDERSTATE_LIGHTING is ignored, it is not defined
5808 * in this d3d version */
5810 /* 0 */
5811 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x0000ff00},
5812 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
5813 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
5814 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
5815 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x0000ff00},
5816 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
5817 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
5818 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
5820 /* 8 */
5821 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x0000ff00},
5822 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
5823 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5824 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5825 /* The specular color in the vertex is ignored because
5826 * D3DRENDERSTATE_COLORVERTEX is not enabled */
5827 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x0000ff00},
5828 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
5829 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5830 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5832 /* 16 */
5833 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
5834 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x00ff0000},
5835 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5836 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5837 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
5838 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x00ff8080},
5839 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5840 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5842 /* 24 */
5843 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
5844 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x00ff0000},
5845 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5846 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5847 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
5848 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x00ff8080},
5849 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5850 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5852 /* 32 */
5853 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
5854 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
5855 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
5856 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
5857 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
5858 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
5859 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
5860 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
5863 window = create_window();
5864 if (!(device = create_device(window, DDSCL_NORMAL)))
5866 skip("Failed to create a 3D device, skipping test.\n");
5867 DestroyWindow(window);
5868 return;
5871 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
5872 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
5874 viewport = create_viewport(device, 0, 0, 640, 480);
5875 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
5876 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
5878 emissive = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
5879 hr = IDirect3DMaterial3_GetHandle(emissive, device, &mat_handle);
5880 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#lx.\n", hr);
5881 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
5882 ok(SUCCEEDED(hr), "Failed to set material state, hr %#lx.\n", hr);
5883 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
5884 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#lx.\n", hr);
5886 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
5887 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#lx.\n", hr);
5888 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#lx, expected FALSE.\n", rs);
5890 for (i = 0; i < ARRAY_SIZE(tests); i++)
5892 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
5893 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
5895 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
5896 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#lx.\n", hr);
5897 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
5898 tests[i].d3drs_specular);
5899 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#lx.\n", hr);
5901 hr = IDirect3DDevice3_BeginScene(device);
5902 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
5903 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
5904 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
5905 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
5906 hr = IDirect3DDevice3_EndScene(device);
5907 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
5909 color = get_surface_color(rt, 320, 240);
5910 ok(compare_color(color, tests[i].color, 1),
5911 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
5912 color, tests[i].color, i);
5915 destroy_material(emissive);
5916 destroy_viewport(device, viewport);
5917 IDirectDrawSurface4_Release(rt);
5918 ref = IDirect3DDevice3_Release(device);
5919 ok(!ref, "Unexpected refcount %lu.\n", ref);
5920 DestroyWindow(window);
5923 static struct
5925 BOOL received;
5926 IDirectDraw4 *ddraw;
5927 HWND window;
5928 DWORD coop_level;
5929 } activateapp_testdata;
5931 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
5933 if (message == WM_ACTIVATEAPP)
5935 if (activateapp_testdata.ddraw)
5937 HRESULT hr;
5938 activateapp_testdata.received = FALSE;
5939 hr = IDirectDraw4_SetCooperativeLevel(activateapp_testdata.ddraw,
5940 activateapp_testdata.window, activateapp_testdata.coop_level);
5941 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#lx.\n", hr);
5942 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
5944 activateapp_testdata.received = TRUE;
5947 return DefWindowProcA(hwnd, message, wparam, lparam);
5950 static void test_coop_level_activateapp(void)
5952 IDirectDraw4 *ddraw;
5953 HRESULT hr;
5954 HWND window;
5955 WNDCLASSA wc = {0};
5956 DDSURFACEDESC2 ddsd;
5957 IDirectDrawSurface4 *surface;
5959 ddraw = create_ddraw();
5960 ok(!!ddraw, "Failed to create a ddraw object.\n");
5962 wc.lpfnWndProc = activateapp_test_proc;
5963 wc.lpszClassName = "ddraw_test_wndproc_wc";
5964 ok(RegisterClassA(&wc), "Failed to register window class.\n");
5966 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
5967 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
5969 /* Exclusive with window already active. */
5970 SetForegroundWindow(window);
5971 activateapp_testdata.received = FALSE;
5972 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5973 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
5974 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
5975 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5976 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
5978 /* Exclusive with window not active. */
5979 SetForegroundWindow(GetDesktopWindow());
5980 activateapp_testdata.received = FALSE;
5981 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5982 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
5983 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5984 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5985 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
5987 /* Normal with window not active, then exclusive with the same window. */
5988 SetForegroundWindow(GetDesktopWindow());
5989 activateapp_testdata.received = FALSE;
5990 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5991 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
5992 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
5993 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5994 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
5995 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5996 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5997 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
5999 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
6000 SetForegroundWindow(GetDesktopWindow());
6001 activateapp_testdata.received = FALSE;
6002 activateapp_testdata.ddraw = ddraw;
6003 activateapp_testdata.window = window;
6004 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
6005 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6006 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6007 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
6008 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
6009 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6011 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
6012 * succeeding. Another switch to exclusive and back to normal is needed to release the
6013 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
6014 * WM_ACTIVATEAPP messages. */
6015 activateapp_testdata.ddraw = NULL;
6016 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6017 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6018 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
6019 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6021 /* Setting DDSCL_NORMAL with recursive invocation. */
6022 SetForegroundWindow(GetDesktopWindow());
6023 activateapp_testdata.received = FALSE;
6024 activateapp_testdata.ddraw = ddraw;
6025 activateapp_testdata.window = window;
6026 activateapp_testdata.coop_level = DDSCL_NORMAL;
6027 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6028 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6029 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
6031 /* DDraw is in exclusive mode now. */
6032 memset(&ddsd, 0, sizeof(ddsd));
6033 ddsd.dwSize = sizeof(ddsd);
6034 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6035 U5(ddsd).dwBackBufferCount = 1;
6036 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6037 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6038 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6039 IDirectDrawSurface4_Release(surface);
6041 /* Recover again, just to be sure. */
6042 activateapp_testdata.ddraw = NULL;
6043 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6044 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6045 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
6046 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6048 DestroyWindow(window);
6049 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
6050 IDirectDraw4_Release(ddraw);
6053 static void test_texturemanage(void)
6055 IDirectDraw4 *ddraw;
6056 HRESULT hr;
6057 DDSURFACEDESC2 ddsd;
6058 IDirectDrawSurface4 *surface;
6059 unsigned int i;
6060 DDCAPS hal_caps, hel_caps;
6061 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
6062 static const struct
6064 DWORD caps_in, caps2_in;
6065 HRESULT hr;
6066 DWORD caps_out, caps2_out;
6068 tests[] =
6070 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
6071 ~0U, ~0U},
6072 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
6073 ~0U, ~0U},
6074 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
6075 ~0U, ~0U},
6076 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
6077 ~0U, ~0U},
6078 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
6079 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
6080 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
6081 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
6082 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
6083 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
6084 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
6085 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
6087 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
6088 ~0U, ~0U},
6089 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
6090 ~0U, ~0U},
6091 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
6092 ~0U, ~0U},
6093 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
6094 ~0U, ~0U},
6095 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
6096 ~0U, ~0U},
6097 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
6098 ~0U, ~0U},
6099 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
6100 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
6101 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
6102 DDSCAPS_SYSTEMMEMORY, 0},
6105 ddraw = create_ddraw();
6106 ok(!!ddraw, "Failed to create a ddraw object.\n");
6107 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
6108 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
6110 memset(&hal_caps, 0, sizeof(hal_caps));
6111 hal_caps.dwSize = sizeof(hal_caps);
6112 memset(&hel_caps, 0, sizeof(hel_caps));
6113 hel_caps.dwSize = sizeof(hel_caps);
6114 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, &hel_caps);
6115 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
6116 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
6118 skip("Managed textures not supported, skipping managed texture test.\n");
6119 IDirectDraw4_Release(ddraw);
6120 return;
6123 for (i = 0; i < ARRAY_SIZE(tests); i++)
6125 memset(&ddsd, 0, sizeof(ddsd));
6126 ddsd.dwSize = sizeof(ddsd);
6127 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
6128 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
6129 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
6130 ddsd.dwWidth = 4;
6131 ddsd.dwHeight = 4;
6133 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6134 ok(hr == tests[i].hr, "Got unexpected, hr %#lx, case %u.\n", hr, i);
6135 if (FAILED(hr))
6136 continue;
6138 memset(&ddsd, 0, sizeof(ddsd));
6139 ddsd.dwSize = sizeof(ddsd);
6140 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6141 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
6143 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
6144 "Input caps %#lx, %#lx, expected output caps %#lx, got %#lx, case %u.\n",
6145 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
6146 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
6147 "Input caps %#lx, %#lx, expected output caps %#lx, got %#lx, case %u.\n",
6148 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
6150 IDirectDrawSurface4_Release(surface);
6153 IDirectDraw4_Release(ddraw);
6156 #define SUPPORT_DXT1 0x01
6157 #define SUPPORT_DXT2 0x02
6158 #define SUPPORT_DXT3 0x04
6159 #define SUPPORT_DXT4 0x08
6160 #define SUPPORT_DXT5 0x10
6161 #define SUPPORT_YUY2 0x20
6162 #define SUPPORT_UYVY 0x40
6164 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
6166 DWORD *supported_fmts = ctx;
6168 if (!(fmt->dwFlags & DDPF_FOURCC))
6169 return DDENUMRET_OK;
6171 switch (fmt->dwFourCC)
6173 case MAKEFOURCC('D','X','T','1'):
6174 *supported_fmts |= SUPPORT_DXT1;
6175 break;
6176 case MAKEFOURCC('D','X','T','2'):
6177 *supported_fmts |= SUPPORT_DXT2;
6178 break;
6179 case MAKEFOURCC('D','X','T','3'):
6180 *supported_fmts |= SUPPORT_DXT3;
6181 break;
6182 case MAKEFOURCC('D','X','T','4'):
6183 *supported_fmts |= SUPPORT_DXT4;
6184 break;
6185 case MAKEFOURCC('D','X','T','5'):
6186 *supported_fmts |= SUPPORT_DXT5;
6187 break;
6188 case MAKEFOURCC('Y','U','Y','2'):
6189 *supported_fmts |= SUPPORT_YUY2;
6190 break;
6191 case MAKEFOURCC('U','Y','V','Y'):
6192 *supported_fmts |= SUPPORT_UYVY;
6193 break;
6194 default:
6195 break;
6198 return DDENUMRET_OK;
6201 static void test_block_formats_creation(void)
6203 HRESULT hr, expect_hr;
6204 unsigned int i, j, w, h;
6205 HWND window;
6206 IDirectDraw4 *ddraw;
6207 IDirect3D3 *d3d;
6208 IDirect3DDevice3 *device;
6209 IDirectDrawSurface4 *surface;
6210 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
6211 DWORD num_fourcc_codes = 0, *fourcc_codes;
6212 DDSURFACEDESC2 ddsd;
6213 DDCAPS hal_caps;
6214 void *mem;
6216 static const struct
6218 DWORD fourcc;
6219 const char *name;
6220 DWORD support_flag;
6221 unsigned int block_width;
6222 unsigned int block_height;
6223 unsigned int block_size;
6224 BOOL create_size_checked, overlay;
6226 formats[] =
6228 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, 8, TRUE, FALSE},
6229 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, 16, TRUE, FALSE},
6230 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, 16, TRUE, FALSE},
6231 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, 16, TRUE, FALSE},
6232 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, 16, TRUE, FALSE},
6233 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, 4, FALSE, TRUE },
6234 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, 4, FALSE, TRUE },
6236 static const struct
6238 DWORD caps, caps2;
6239 const char *name;
6240 BOOL overlay;
6242 types[] =
6244 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
6245 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
6247 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
6248 * Other hw / drivers successfully create those surfaces. Ignore them, this
6249 * suggests that no game uses this, otherwise Nvidia would support it. */
6251 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
6252 "videomemory texture", FALSE
6255 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
6256 "videomemory overlay", TRUE
6259 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
6260 "systemmemory texture", FALSE
6263 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
6264 "managed texture", FALSE
6267 enum size_type
6269 SIZE_TYPE_ZERO,
6270 SIZE_TYPE_PITCH,
6271 SIZE_TYPE_SIZE,
6273 static const struct
6275 DWORD flags;
6276 enum size_type size_type;
6277 int rel_size;
6278 HRESULT hr;
6280 user_mem_tests[] =
6282 {DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DD_OK},
6283 {DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
6284 {DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
6285 {DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
6286 {DDSD_LPSURFACE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
6287 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
6288 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
6289 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
6290 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 1, DD_OK},
6291 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, -1, DDERR_INVALIDPARAMS},
6292 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
6293 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
6294 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_SIZE, 0, DD_OK},
6295 {DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
6298 window = create_window();
6299 if (!(device = create_device(window, DDSCL_NORMAL)))
6301 skip("Failed to create a 3D device, skipping test.\n");
6302 DestroyWindow(window);
6303 return;
6306 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
6307 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
6308 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **) &ddraw);
6309 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#lx.\n", hr);
6310 IDirect3D3_Release(d3d);
6312 hr = IDirect3DDevice3_EnumTextureFormats(device, test_block_formats_creation_cb,
6313 &supported_fmts);
6314 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
6316 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
6317 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
6318 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6319 num_fourcc_codes * sizeof(*fourcc_codes));
6320 if (!fourcc_codes)
6321 goto cleanup;
6322 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
6323 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
6324 for (i = 0; i < num_fourcc_codes; i++)
6326 for (j = 0; j < ARRAY_SIZE(formats); j++)
6328 if (fourcc_codes[i] == formats[j].fourcc)
6329 supported_overlay_fmts |= formats[j].support_flag;
6332 HeapFree(GetProcessHeap(), 0, fourcc_codes);
6334 memset(&hal_caps, 0, sizeof(hal_caps));
6335 hal_caps.dwSize = sizeof(hal_caps);
6336 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
6337 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
6339 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * 2 * 16 + 1);
6341 for (i = 0; i < ARRAY_SIZE(formats); i++)
6343 for (j = 0; j < ARRAY_SIZE(types); j++)
6345 BOOL support;
6347 if (formats[i].overlay != types[j].overlay
6348 || (types[j].overlay && !(hal_caps.dwCaps & DDCAPS_OVERLAY)))
6349 continue;
6351 if (formats[i].overlay)
6352 support = supported_overlay_fmts & formats[i].support_flag;
6353 else
6354 support = supported_fmts & formats[i].support_flag;
6356 for (w = 1; w <= 8; w++)
6358 for (h = 1; h <= 8; h++)
6360 BOOL block_aligned = TRUE;
6361 BOOL todo = FALSE;
6363 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
6364 block_aligned = FALSE;
6366 memset(&ddsd, 0, sizeof(ddsd));
6367 ddsd.dwSize = sizeof(ddsd);
6368 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
6369 ddsd.ddsCaps.dwCaps = types[j].caps;
6370 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
6371 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6372 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
6373 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
6374 ddsd.dwWidth = w;
6375 ddsd.dwHeight = h;
6377 /* TODO: Handle power of two limitations. I cannot test the pow2
6378 * behavior on windows because I have no hardware that doesn't at
6379 * least support np2_conditional. There's probably no HW that
6380 * supports DXTN textures but no conditional np2 textures. */
6381 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
6382 expect_hr = DDERR_INVALIDPARAMS;
6383 else if (formats[i].create_size_checked && !block_aligned)
6385 expect_hr = DDERR_INVALIDPARAMS;
6386 if (!(types[j].caps & DDSCAPS_TEXTURE))
6387 todo = TRUE;
6389 else
6390 expect_hr = D3D_OK;
6392 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6393 todo_wine_if (todo)
6394 ok(hr == expect_hr,
6395 "Got unexpected hr %#lx for format %s, resource type %s, size %ux%u, expected %#lx.\n",
6396 hr, formats[i].name, types[j].name, w, h, expect_hr);
6398 if (SUCCEEDED(hr))
6399 IDirectDrawSurface4_Release(surface);
6404 if (formats[i].overlay)
6405 continue;
6407 for (j = 0; j < ARRAY_SIZE(user_mem_tests); ++j)
6409 memset(&ddsd, 0, sizeof(ddsd));
6410 ddsd.dwSize = sizeof(ddsd);
6411 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | user_mem_tests[j].flags;
6412 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
6414 switch (user_mem_tests[j].size_type)
6416 case SIZE_TYPE_ZERO:
6417 U1(ddsd).dwLinearSize = 0;
6418 break;
6420 case SIZE_TYPE_PITCH:
6421 U1(ddsd).dwLinearSize = 2 * formats[i].block_size;
6422 break;
6424 case SIZE_TYPE_SIZE:
6425 U1(ddsd).dwLinearSize = 2 * 2 * formats[i].block_size;
6426 break;
6428 U1(ddsd).dwLinearSize += user_mem_tests[j].rel_size;
6430 ddsd.lpSurface = mem;
6431 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6432 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
6433 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
6434 ddsd.dwWidth = 8;
6435 ddsd.dwHeight = 8;
6437 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6438 ok(hr == user_mem_tests[j].hr, "Test %u: Got unexpected hr %#lx, format %s.\n", j, hr, formats[i].name);
6440 if (FAILED(hr))
6441 continue;
6443 memset(&ddsd, 0, sizeof(ddsd));
6444 ddsd.dwSize = sizeof(ddsd);
6445 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6446 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#lx.\n", j, hr);
6447 ok(ddsd.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE),
6448 "Test %u: Got unexpected flags %#lx.\n", j, ddsd.dwFlags);
6449 if (user_mem_tests[j].flags & DDSD_LPSURFACE)
6450 ok(U1(ddsd).dwLinearSize == ~0u, "Test %u: Got unexpected linear size %#lx.\n",
6451 j, U1(ddsd).dwLinearSize);
6452 else
6453 ok(U1(ddsd).dwLinearSize == 2 * 2 * formats[i].block_size,
6454 "Test %u: Got unexpected linear size %#lx, expected %#x.\n",
6455 j, U1(ddsd).dwLinearSize, 2 * 2 * formats[i].block_size);
6456 IDirectDrawSurface4_Release(surface);
6460 HeapFree(GetProcessHeap(), 0, mem);
6461 cleanup:
6462 IDirectDraw4_Release(ddraw);
6463 IDirect3DDevice3_Release(device);
6464 DestroyWindow(window);
6467 struct format_support_check
6469 const DDPIXELFORMAT *format;
6470 BOOL supported;
6473 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
6475 struct format_support_check *format = ctx;
6477 if (!memcmp(format->format, fmt, sizeof(*fmt)))
6479 format->supported = TRUE;
6480 return DDENUMRET_CANCEL;
6483 return DDENUMRET_OK;
6486 static void test_unsupported_formats(void)
6488 HRESULT hr;
6489 BOOL expect_success;
6490 HWND window;
6491 IDirectDraw4 *ddraw;
6492 IDirect3D3 *d3d;
6493 IDirect3DDevice3 *device;
6494 IDirectDrawSurface4 *surface;
6495 DDSURFACEDESC2 ddsd;
6496 unsigned int i, j;
6497 DWORD expected_caps;
6498 static const struct
6500 const char *name;
6501 DDPIXELFORMAT fmt;
6503 formats[] =
6506 "D3DFMT_A8R8G8B8",
6508 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
6509 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
6513 "D3DFMT_P8",
6515 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
6516 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
6520 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
6522 window = create_window();
6523 if (!(device = create_device(window, DDSCL_NORMAL)))
6525 skip("Failed to create a 3D device, skipping test.\n");
6526 DestroyWindow(window);
6527 return;
6530 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
6531 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
6532 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **) &ddraw);
6533 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#lx.\n", hr);
6534 IDirect3D3_Release(d3d);
6536 for (i = 0; i < ARRAY_SIZE(formats); i++)
6538 struct format_support_check check = {&formats[i].fmt, FALSE};
6539 hr = IDirect3DDevice3_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
6540 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
6542 for (j = 0; j < ARRAY_SIZE(caps); j++)
6544 memset(&ddsd, 0, sizeof(ddsd));
6545 ddsd.dwSize = sizeof(ddsd);
6546 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6547 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
6548 ddsd.dwWidth = 4;
6549 ddsd.dwHeight = 4;
6550 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
6552 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
6553 expect_success = FALSE;
6554 else
6555 expect_success = TRUE;
6557 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
6558 ok(SUCCEEDED(hr) == expect_success,
6559 "Got unexpected hr %#lx for format %s, caps %#lx, expected %s.\n",
6560 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
6561 if (FAILED(hr))
6562 continue;
6564 memset(&ddsd, 0, sizeof(ddsd));
6565 ddsd.dwSize = sizeof(ddsd);
6566 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
6567 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
6569 if (caps[j] & DDSCAPS_VIDEOMEMORY)
6570 expected_caps = DDSCAPS_VIDEOMEMORY;
6571 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
6572 expected_caps = DDSCAPS_SYSTEMMEMORY;
6573 else if (check.supported)
6574 expected_caps = DDSCAPS_VIDEOMEMORY;
6575 else
6576 expected_caps = DDSCAPS_SYSTEMMEMORY;
6578 ok(ddsd.ddsCaps.dwCaps & expected_caps,
6579 "Expected caps %#lx, format %s, input caps %#lx.\n",
6580 expected_caps, formats[i].name, caps[j]);
6582 IDirectDrawSurface4_Release(surface);
6586 IDirectDraw4_Release(ddraw);
6587 IDirect3DDevice3_Release(device);
6588 DestroyWindow(window);
6591 static void test_rt_caps(const GUID *device_guid)
6593 PALETTEENTRY palette_entries[256];
6594 IDirectDrawPalette *palette;
6595 BOOL software_device;
6596 IDirectDraw4 *ddraw;
6597 DDPIXELFORMAT z_fmt;
6598 IDirect3D3 *d3d;
6599 DDCAPS hal_caps;
6600 unsigned int i;
6601 ULONG refcount;
6602 HWND window;
6603 HRESULT hr;
6605 static const DDPIXELFORMAT p8_fmt =
6607 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
6608 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
6611 const struct
6613 const DDPIXELFORMAT *pf;
6614 DWORD caps_in;
6615 DWORD caps2_in;
6616 HRESULT create_device_hr;
6617 HRESULT set_rt_hr, alternative_set_rt_hr;
6619 test_data[] =
6622 NULL,
6623 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
6625 D3D_OK,
6626 D3D_OK,
6627 D3D_OK,
6630 NULL,
6631 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
6633 D3D_OK,
6634 D3D_OK,
6635 D3D_OK,
6638 NULL,
6639 DDSCAPS_OFFSCREENPLAIN,
6641 DDERR_INVALIDCAPS,
6642 DDERR_INVALIDCAPS,
6643 DDERR_INVALIDCAPS,
6646 NULL,
6647 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
6649 D3DERR_SURFACENOTINVIDMEM,
6650 D3D_OK,
6651 D3D_OK,
6654 NULL,
6655 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
6657 DDERR_INVALIDCAPS,
6658 DDERR_INVALIDCAPS,
6659 DDERR_INVALIDCAPS,
6662 NULL,
6663 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
6665 D3D_OK,
6666 D3D_OK,
6667 D3D_OK,
6670 NULL,
6671 DDSCAPS_3DDEVICE,
6673 D3D_OK,
6674 D3D_OK,
6675 D3D_OK,
6678 NULL,
6681 DDERR_INVALIDCAPS,
6682 DDERR_INVALIDCAPS,
6683 DDERR_INVALIDCAPS,
6686 NULL,
6687 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
6689 D3DERR_SURFACENOTINVIDMEM,
6690 D3D_OK,
6691 D3D_OK,
6694 NULL,
6695 DDSCAPS_SYSTEMMEMORY,
6697 DDERR_INVALIDCAPS,
6698 DDERR_INVALIDCAPS,
6699 DDERR_INVALIDCAPS,
6702 NULL,
6703 DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE,
6704 DDSCAPS2_TEXTUREMANAGE,
6705 D3DERR_SURFACENOTINVIDMEM,
6706 D3D_OK,
6707 D3D_OK,
6710 NULL,
6711 DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE,
6712 DDSCAPS2_D3DTEXTUREMANAGE,
6713 D3DERR_SURFACENOTINVIDMEM,
6714 D3D_OK,
6715 D3D_OK,
6718 &p8_fmt,
6721 DDERR_INVALIDCAPS,
6722 DDERR_INVALIDCAPS,
6723 DDERR_INVALIDCAPS,
6726 &p8_fmt,
6727 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
6729 DDERR_NOPALETTEATTACHED,
6730 DDERR_INVALIDCAPS,
6731 DDERR_INVALIDCAPS,
6734 &p8_fmt,
6735 DDSCAPS_OFFSCREENPLAIN,
6737 DDERR_INVALIDCAPS,
6738 DDERR_INVALIDCAPS,
6739 DDERR_INVALIDCAPS,
6742 &p8_fmt,
6743 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
6745 DDERR_NOPALETTEATTACHED,
6746 DDERR_INVALIDCAPS,
6747 DDERR_INVALIDCAPS,
6750 &p8_fmt,
6751 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
6753 DDERR_INVALIDCAPS,
6754 DDERR_INVALIDCAPS,
6755 DDERR_INVALIDCAPS,
6758 &z_fmt,
6759 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
6761 DDERR_INVALIDCAPS,
6762 DDERR_INVALIDPIXELFORMAT,
6763 D3D_OK /* r200 */,
6766 &z_fmt,
6767 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
6769 DDERR_INVALIDCAPS,
6770 DDERR_INVALIDPIXELFORMAT,
6771 D3D_OK /* r200 */,
6774 &z_fmt,
6775 DDSCAPS_ZBUFFER,
6777 DDERR_INVALIDCAPS,
6778 DDERR_INVALIDCAPS,
6779 DDERR_INVALIDCAPS,
6782 &z_fmt,
6783 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
6785 DDERR_INVALIDCAPS,
6786 DDERR_INVALIDPIXELFORMAT,
6787 D3D_OK /* r200 */,
6790 &z_fmt,
6791 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
6793 DDERR_INVALIDCAPS,
6794 DDERR_INVALIDCAPS,
6795 DDERR_INVALIDCAPS,
6799 software_device = is_software_device_type(device_guid);
6801 window = create_window();
6802 ddraw = create_ddraw();
6803 ok(!!ddraw, "Failed to create a ddraw object.\n");
6804 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6805 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
6807 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
6809 skip("D3D interface is not available, skipping test.\n");
6810 goto done;
6813 memset(&z_fmt, 0, sizeof(z_fmt));
6814 hr = IDirect3D3_EnumZBufferFormats(d3d, device_guid, enum_z_fmt, &z_fmt);
6815 if (FAILED(hr) || !z_fmt.dwSize)
6817 skip("No depth buffer formats available, software_device %u, skipping test.\n", software_device);
6818 IDirect3D3_Release(d3d);
6819 goto done;
6822 memset(palette_entries, 0, sizeof(palette_entries));
6823 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
6824 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
6826 memset(&hal_caps, 0, sizeof(hal_caps));
6827 hal_caps.dwSize = sizeof(hal_caps);
6828 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
6829 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
6831 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6833 IDirectDrawSurface4 *surface, *rt, *expected_rt, *tmp;
6834 DWORD caps_in, expected_caps;
6835 DDSURFACEDESC2 surface_desc;
6836 IDirect3DDevice3 *device;
6837 HRESULT expected_hr;
6839 caps_in = test_data[i].caps_in;
6841 memset(&surface_desc, 0, sizeof(surface_desc));
6842 surface_desc.dwSize = sizeof(surface_desc);
6843 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6844 surface_desc.ddsCaps.dwCaps = caps_in;
6845 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2_in;
6846 if (test_data[i].pf)
6848 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
6849 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
6851 surface_desc.dwWidth = 640;
6852 surface_desc.dwHeight = 480;
6853 if ((caps_in & DDSCAPS_VIDEOMEMORY) && !(hal_caps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6854 expected_hr = DDERR_NODIRECTDRAWHW;
6855 else
6856 expected_hr = DD_OK;
6857 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6858 ok(hr == expected_hr || (software_device && (surface_desc.ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER))
6859 == (DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER) && hr == DDERR_UNSUPPORTED)
6860 || broken(software_device && test_data[i].pf == &p8_fmt && hr == DDERR_INVALIDPIXELFORMAT),
6861 "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
6862 if (FAILED(hr))
6863 continue;
6865 memset(&surface_desc, 0, sizeof(surface_desc));
6866 surface_desc.dwSize = sizeof(surface_desc);
6867 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
6868 ok(hr == DD_OK, "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
6870 if ((caps_in & DDSCAPS_SYSTEMMEMORY) || (test_data[i].caps2_in & (DDSCAPS2_D3DTEXTUREMANAGE
6871 | DDSCAPS2_TEXTUREMANAGE)) || !(hal_caps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6872 expected_caps = caps_in | DDSCAPS_SYSTEMMEMORY;
6873 else
6874 expected_caps = caps_in | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
6876 ok(surface_desc.ddsCaps.dwCaps == expected_caps || (test_data[i].pf == &p8_fmt
6877 && surface_desc.ddsCaps.dwCaps == (caps_in | DDSCAPS_SYSTEMMEMORY))
6878 || (software_device && test_data[i].pf == &z_fmt
6879 && surface_desc.ddsCaps.dwCaps == (caps_in | DDSCAPS_SYSTEMMEMORY)),
6880 "Got unexpected caps %#lx, expected %#lx, test %u, software_device %u.\n",
6881 surface_desc.ddsCaps.dwCaps, expected_caps, i, software_device);
6883 ok(surface_desc.ddsCaps.dwCaps2 == test_data[i].caps2_in,
6884 "Got unexpected caps2 %#lx, expected %#lx, test %u, software_device %u.\n",
6885 surface_desc.ddsCaps.dwCaps2, test_data[i].caps2_in, i, software_device);
6887 hr = IDirect3D3_CreateDevice(d3d, device_guid, surface, &device, NULL);
6889 ok((!software_device && hr == test_data[i].create_device_hr)
6890 || (software_device && (hr == (test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM
6891 ? DD_OK : test_data[i].create_device_hr))),
6892 "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
6893 if (FAILED(hr))
6895 if (hr == DDERR_NOPALETTEATTACHED)
6897 hr = IDirectDrawSurface4_SetPalette(surface, palette);
6898 ok(hr == DD_OK, "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
6899 if (software_device)
6901 /* _CreateDevice succeeds with software device, but the palette gets extra reference
6902 * on Windows (probably due to a bug) which doesn't go away on the device and surface
6903 * destruction and ddraw is not destroyed cleanly, so skipping this test. */
6904 IDirectDrawSurface4_Release(surface);
6905 continue;
6907 hr = IDirect3D3_CreateDevice(d3d, device_guid, surface, &device, NULL);
6908 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
6909 ok(hr == DDERR_INVALIDPIXELFORMAT, "Got unexpected hr %#lx, test %u, software_device %u.\n",
6910 hr, i, software_device);
6911 else
6912 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Got unexpected hr %#lx, test %u, software_device %u.\n",
6913 hr, i, software_device);
6915 IDirectDrawSurface4_Release(surface);
6917 memset(&surface_desc, 0, sizeof(surface_desc));
6918 surface_desc.dwSize = sizeof(surface_desc);
6919 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6920 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6921 surface_desc.dwWidth = 640;
6922 surface_desc.dwHeight = 480;
6923 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6924 ok(hr == DD_OK, "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
6926 hr = IDirect3D3_CreateDevice(d3d, device_guid, surface, &device, NULL);
6927 ok(hr == DD_OK, "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
6930 memset(&surface_desc, 0, sizeof(surface_desc));
6931 surface_desc.dwSize = sizeof(surface_desc);
6932 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6933 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
6934 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2_in;
6935 if (test_data[i].pf)
6937 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
6938 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
6940 surface_desc.dwWidth = 640;
6941 surface_desc.dwHeight = 480;
6942 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &rt, NULL);
6943 ok(hr == DD_OK, "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
6945 hr = IDirect3DDevice3_SetRenderTarget(device, rt, 0);
6946 ok(hr == test_data[i].set_rt_hr || (software_device && hr == DDERR_NOPALETTEATTACHED)
6947 || broken(hr == test_data[i].alternative_set_rt_hr),
6948 "Got unexpected hr %#lx, test %u, software_device %u.\n",
6949 hr, i, software_device);
6950 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
6951 expected_rt = rt;
6952 else
6953 expected_rt = surface;
6955 hr = IDirect3DDevice3_GetRenderTarget(device, &tmp);
6956 ok(hr == DD_OK, "Got unexpected hr %#lx, test %u, software_device %u.\n", hr, i, software_device);
6957 ok(tmp == expected_rt, "Got unexpected rt %p, test %u, software_device %u.\n", tmp, i, software_device);
6959 IDirectDrawSurface4_Release(tmp);
6960 IDirectDrawSurface4_Release(rt);
6961 refcount = IDirect3DDevice3_Release(device);
6962 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
6963 refcount = IDirectDrawSurface4_Release(surface);
6964 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
6967 refcount = IDirectDrawPalette_Release(palette);
6968 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
6969 IDirect3D3_Release(d3d);
6971 done:
6972 refcount = IDirectDraw4_Release(ddraw);
6973 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
6974 DestroyWindow(window);
6977 static void test_primary_caps(void)
6979 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
6980 IDirectDrawSurface4 *surface;
6981 DDSURFACEDESC2 surface_desc;
6982 IDirectDraw4 *ddraw;
6983 unsigned int i;
6984 ULONG refcount;
6985 HWND window;
6986 HRESULT hr;
6988 static const struct
6990 DWORD coop_level;
6991 DWORD caps_in;
6992 DWORD back_buffer_count;
6993 HRESULT hr;
6994 DWORD caps_out;
6996 test_data[] =
6999 DDSCL_NORMAL,
7000 DDSCAPS_PRIMARYSURFACE,
7001 ~0u,
7002 DD_OK,
7003 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
7006 DDSCL_NORMAL,
7007 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
7008 ~0u,
7009 DDERR_INVALIDCAPS,
7010 ~0u,
7013 DDSCL_NORMAL,
7014 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
7015 ~0u,
7016 DDERR_INVALIDCAPS,
7017 ~0u,
7020 DDSCL_NORMAL,
7021 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
7022 ~0u,
7023 DDERR_INVALIDCAPS,
7024 ~0u,
7027 DDSCL_NORMAL,
7028 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
7029 ~0u,
7030 DDERR_INVALIDCAPS,
7031 ~0u,
7034 DDSCL_NORMAL,
7035 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
7036 ~0u,
7037 DDERR_INVALIDCAPS,
7038 ~0u,
7041 DDSCL_NORMAL,
7042 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
7043 ~0u,
7044 DDERR_INVALIDCAPS,
7045 ~0u,
7048 DDSCL_NORMAL,
7049 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
7051 DDERR_INVALIDCAPS,
7052 ~0u,
7055 DDSCL_NORMAL,
7056 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
7058 DDERR_NOEXCLUSIVEMODE,
7059 ~0u,
7062 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
7063 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
7065 DDERR_INVALIDCAPS,
7066 ~0u,
7069 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
7070 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
7072 DD_OK,
7073 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
7076 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
7077 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
7079 DDERR_INVALIDCAPS,
7080 ~0u,
7083 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
7084 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
7086 DDERR_INVALIDCAPS,
7087 ~0u,
7091 window = create_window();
7092 ddraw = create_ddraw();
7093 ok(!!ddraw, "Failed to create a ddraw object.\n");
7095 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7097 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
7098 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
7100 memset(&surface_desc, 0, sizeof(surface_desc));
7101 surface_desc.dwSize = sizeof(surface_desc);
7102 surface_desc.dwFlags = DDSD_CAPS;
7103 if (test_data[i].back_buffer_count != ~0u)
7104 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
7105 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
7106 U5(surface_desc).dwBackBufferCount = test_data[i].back_buffer_count;
7107 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7108 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n", i, hr, test_data[i].hr);
7109 if (FAILED(hr))
7110 continue;
7112 memset(&surface_desc, 0, sizeof(surface_desc));
7113 surface_desc.dwSize = sizeof(surface_desc);
7114 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
7115 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#lx.\n", i, hr);
7116 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
7117 "Test %u: Got unexpected caps %#lx, expected %#lx.\n",
7118 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
7120 IDirectDrawSurface4_Release(surface);
7123 refcount = IDirectDraw4_Release(ddraw);
7124 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
7125 DestroyWindow(window);
7128 static void test_surface_lock(void)
7130 IDirectDraw4 *ddraw;
7131 IDirect3D3 *d3d = NULL;
7132 IDirectDrawSurface4 *surface;
7133 HRESULT hr;
7134 HWND window;
7135 unsigned int i;
7136 DDSURFACEDESC2 ddsd;
7137 ULONG refcount;
7138 DDPIXELFORMAT z_fmt;
7139 static const struct
7141 DWORD caps;
7142 DWORD caps2;
7143 const char *name;
7145 tests[] =
7148 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
7150 "videomemory offscreenplain"
7153 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
7155 "systemmemory offscreenplain"
7158 DDSCAPS_PRIMARYSURFACE,
7160 "primary"
7163 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
7165 "videomemory texture"
7168 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
7169 DDSCAPS2_OPAQUE,
7170 "opaque videomemory texture"
7173 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
7175 "systemmemory texture"
7178 DDSCAPS_TEXTURE,
7179 DDSCAPS2_TEXTUREMANAGE,
7180 "managed texture"
7183 DDSCAPS_TEXTURE,
7184 DDSCAPS2_D3DTEXTUREMANAGE,
7185 "managed texture"
7188 DDSCAPS_TEXTURE,
7189 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
7190 "opaque managed texture"
7193 DDSCAPS_TEXTURE,
7194 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
7195 "opaque managed texture"
7198 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
7200 "render target"
7203 DDSCAPS_ZBUFFER,
7205 "Z buffer"
7209 window = create_window();
7210 ddraw = create_ddraw();
7211 ok(!!ddraw, "Failed to create a ddraw object.\n");
7212 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7213 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
7215 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
7217 skip("D3D interface is not available, skipping test.\n");
7218 goto done;
7221 memset(&z_fmt, 0, sizeof(z_fmt));
7222 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
7223 if (FAILED(hr) || !z_fmt.dwSize)
7225 skip("No depth buffer formats available, skipping test.\n");
7226 goto done;
7229 for (i = 0; i < ARRAY_SIZE(tests); i++)
7231 memset(&ddsd, 0, sizeof(ddsd));
7232 ddsd.dwSize = sizeof(ddsd);
7233 ddsd.dwFlags = DDSD_CAPS;
7234 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
7236 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
7237 ddsd.dwWidth = 64;
7238 ddsd.dwHeight = 64;
7240 if (tests[i].caps & DDSCAPS_ZBUFFER)
7242 ddsd.dwFlags |= DDSD_PIXELFORMAT;
7243 U4(ddsd).ddpfPixelFormat = z_fmt;
7245 ddsd.ddsCaps.dwCaps = tests[i].caps;
7246 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
7248 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
7249 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#lx.\n", tests[i].name, hr);
7251 memset(&ddsd, 0, sizeof(ddsd));
7252 ddsd.dwSize = sizeof(ddsd);
7253 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
7254 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#lx.\n", tests[i].name, hr);
7255 if (SUCCEEDED(hr))
7257 hr = IDirectDrawSurface4_Unlock(surface, NULL);
7258 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#lx.\n", tests[i].name, hr);
7261 memset(&ddsd, 0, sizeof(ddsd));
7262 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
7263 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx, type %s.\n", hr, tests[i].name);
7265 IDirectDrawSurface4_Release(surface);
7268 done:
7269 if (d3d)
7270 IDirect3D3_Release(d3d);
7271 refcount = IDirectDraw4_Release(ddraw);
7272 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
7273 DestroyWindow(window);
7276 static void test_surface_discard(void)
7278 IDirect3DDevice3 *device;
7279 IDirect3D3 *d3d;
7280 IDirectDraw4 *ddraw;
7281 HRESULT hr;
7282 HWND window;
7283 DDSURFACEDESC2 ddsd;
7284 IDirectDrawSurface4 *surface, *target;
7285 void *addr;
7286 static const struct
7288 DWORD caps, caps2;
7289 BOOL discard;
7291 tests[] =
7293 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
7294 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
7295 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
7296 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
7297 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
7298 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
7299 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
7300 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
7302 unsigned int i;
7304 window = create_window();
7306 for (i = 0; i < ARRAY_SIZE(tests); i++)
7308 BOOL discarded;
7310 /* Sigh. Anything other than the first run of the loop randomly fails with
7311 * DDERR_SURFACELOST on my Radeon Pro 560 on Win10 19.09. Most of the time
7312 * the blit fails, but with sleeps added between surface creation and lock
7313 * the lock can fail too. Interestingly ddraw claims the render target has
7314 * been lost, not the test surface.
7316 * Recreating ddraw every iteration seems to fix this. */
7317 if (!(device = create_device(window, DDSCL_NORMAL)))
7319 skip("Failed to create a 3D device, skipping test.\n");
7320 DestroyWindow(window);
7321 return;
7323 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
7324 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
7325 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
7326 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#lx.\n", hr);
7327 hr = IDirect3DDevice3_GetRenderTarget(device, &target);
7328 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
7330 memset(&ddsd, 0, sizeof(ddsd));
7331 ddsd.dwSize = sizeof(ddsd);
7332 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7333 ddsd.ddsCaps.dwCaps = tests[i].caps;
7334 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
7335 ddsd.dwWidth = 64;
7336 ddsd.dwHeight = 64;
7337 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
7338 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#lx, case %u.\n", hr, i);
7340 memset(&ddsd, 0, sizeof(ddsd));
7341 ddsd.dwSize = sizeof(ddsd);
7342 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, 0, NULL);
7343 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
7344 addr = ddsd.lpSurface;
7345 hr = IDirectDrawSurface4_Unlock(surface, NULL);
7346 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
7348 memset(&ddsd, 0, sizeof(ddsd));
7349 ddsd.dwSize = sizeof(ddsd);
7350 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
7351 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
7352 discarded = ddsd.lpSurface != addr;
7353 hr = IDirectDrawSurface4_Unlock(surface, NULL);
7354 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
7356 hr = IDirectDrawSurface4_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
7357 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
7359 memset(&ddsd, 0, sizeof(ddsd));
7360 ddsd.dwSize = sizeof(ddsd);
7361 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
7362 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
7363 discarded |= ddsd.lpSurface != addr;
7364 hr = IDirectDrawSurface4_Unlock(surface, NULL);
7365 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
7367 IDirectDrawSurface4_Release(surface);
7369 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
7370 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
7371 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
7373 IDirectDrawSurface4_Release(target);
7374 IDirectDraw4_Release(ddraw);
7375 IDirect3D3_Release(d3d);
7376 IDirect3DDevice3_Release(device);
7379 DestroyWindow(window);
7382 static void test_flip(void)
7384 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
7385 IDirectDrawSurface4 *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
7386 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
7387 DDSURFACEDESC2 surface_desc;
7388 unsigned int color, i;
7389 BOOL sysmem_primary;
7390 IDirectDraw4 *ddraw;
7391 DWORD expected_caps;
7392 ULONG refcount;
7393 HWND window;
7394 HRESULT hr;
7396 static const struct
7398 const char *name;
7399 DWORD caps;
7401 test_data[] =
7403 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
7404 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
7405 {"TEXTURE", DDSCAPS_TEXTURE},
7408 window = create_window();
7409 ddraw = create_ddraw();
7410 ok(!!ddraw, "Failed to create a ddraw object.\n");
7412 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7413 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
7415 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7417 /* Creating a flippable texture induces a BSoD on some versions of the
7418 * Intel graphics driver. At least Intel GMA 950 with driver version
7419 * 6.14.10.4926 on Windows XP SP3 is affected. */
7420 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
7422 win_skip("Skipping flippable texture test.\n");
7423 continue;
7426 memset(&surface_desc, 0, sizeof(surface_desc));
7427 surface_desc.dwSize = sizeof(surface_desc);
7428 surface_desc.dwFlags = DDSD_CAPS;
7429 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
7430 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
7431 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
7432 surface_desc.dwWidth = 512;
7433 surface_desc.dwHeight = 512;
7434 U5(surface_desc).dwBackBufferCount = 3;
7435 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7436 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
7438 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
7439 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
7440 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7441 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
7443 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
7444 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
7445 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7446 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
7448 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
7449 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7450 todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
7451 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#lx.\n", test_data[i].name, hr);
7452 if (FAILED(hr))
7453 continue;
7455 memset(&surface_desc, 0, sizeof(surface_desc));
7456 surface_desc.dwSize = sizeof(surface_desc);
7457 hr = IDirectDrawSurface4_GetSurfaceDesc(frontbuffer, &surface_desc);
7458 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#lx.\n", test_data[i].name, hr);
7459 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
7460 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
7461 expected_caps |= DDSCAPS_VISIBLE;
7462 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
7463 "%s: Got unexpected caps %#lx.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
7464 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
7466 hr = IDirectDrawSurface4_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
7467 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#lx.\n", test_data[i].name, hr);
7468 memset(&surface_desc, 0, sizeof(surface_desc));
7469 surface_desc.dwSize = sizeof(surface_desc);
7470 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer1, &surface_desc);
7471 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#lx.\n", test_data[i].name, hr);
7472 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %lu.\n",
7473 test_data[i].name, U5(surface_desc).dwBackBufferCount);
7474 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
7475 expected_caps |= DDSCAPS_BACKBUFFER;
7476 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
7477 "%s: Got unexpected caps %#lx.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
7479 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
7480 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#lx.\n", test_data[i].name, hr);
7481 memset(&surface_desc, 0, sizeof(surface_desc));
7482 surface_desc.dwSize = sizeof(surface_desc);
7483 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer2, &surface_desc);
7484 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#lx.\n", test_data[i].name, hr);
7485 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %lu.\n",
7486 test_data[i].name, U5(surface_desc).dwBackBufferCount);
7487 expected_caps &= ~DDSCAPS_BACKBUFFER;
7488 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
7489 "%s: Got unexpected caps %#lx.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
7491 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
7492 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#lx.\n", test_data[i].name, hr);
7493 memset(&surface_desc, 0, sizeof(surface_desc));
7494 surface_desc.dwSize = sizeof(surface_desc);
7495 hr = IDirectDrawSurface4_GetSurfaceDesc(backbuffer3, &surface_desc);
7496 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#lx.\n", test_data[i].name, hr);
7497 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %lu.\n",
7498 test_data[i].name, U5(surface_desc).dwBackBufferCount);
7499 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
7500 "%s: Got unexpected caps %#lx.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
7502 hr = IDirectDrawSurface4_GetAttachedSurface(backbuffer3, &caps, &surface);
7503 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#lx.\n", test_data[i].name, hr);
7504 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
7505 test_data[i].name, surface, frontbuffer);
7506 IDirectDrawSurface4_Release(surface);
7508 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
7509 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#lx.\n", test_data[i].name, hr);
7510 hr = IDirectDrawSurface4_IsLost(frontbuffer);
7511 ok(hr == DD_OK, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
7512 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
7513 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
7514 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
7515 else
7516 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
7517 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7518 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#lx.\n", test_data[i].name, hr);
7519 hr = IDirectDrawSurface4_IsLost(frontbuffer);
7520 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
7521 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
7522 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#lx.\n", test_data[i].name, hr);
7524 memset(&surface_desc, 0, sizeof(surface_desc));
7525 surface_desc.dwSize = sizeof(surface_desc);
7526 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7527 surface_desc.ddsCaps.dwCaps = 0;
7528 surface_desc.dwWidth = 640;
7529 surface_desc.dwHeight = 480;
7530 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7531 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#lx.\n", test_data[i].name, hr);
7532 hr = IDirectDrawSurface4_Flip(frontbuffer, surface, DDFLIP_WAIT);
7533 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
7534 IDirectDrawSurface4_Release(surface);
7536 hr = IDirectDrawSurface4_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
7537 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
7538 hr = IDirectDrawSurface4_Flip(backbuffer1, NULL, DDFLIP_WAIT);
7539 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
7540 hr = IDirectDrawSurface4_Flip(backbuffer2, NULL, DDFLIP_WAIT);
7541 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
7542 hr = IDirectDrawSurface4_Flip(backbuffer3, NULL, DDFLIP_WAIT);
7543 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#lx.\n", test_data[i].name, hr);
7545 /* The Nvidia Geforce 7 driver cannot do a color fill on a texture backbuffer after
7546 * the backbuffer has been locked. Do it ourselves as a workaround. Unlike ddraw1
7547 * and 2 GetSurfaceDesc does not cause issues in ddraw4 and ddraw7. */
7548 fill_surface(backbuffer1, 0xffff0000);
7549 fill_surface(backbuffer2, 0xff00ff00);
7550 fill_surface(backbuffer3, 0xff0000ff);
7552 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
7553 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
7554 color = get_surface_color(backbuffer1, 320, 240);
7555 /* The testbot seems to just copy the contents of one surface to all the
7556 * others, instead of properly flipping. */
7557 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
7558 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7559 color = get_surface_color(backbuffer2, 320, 240);
7560 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7561 fill_surface(backbuffer3, 0xffff0000);
7563 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
7564 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
7565 color = get_surface_color(backbuffer1, 320, 240);
7566 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
7567 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7568 color = get_surface_color(backbuffer2, 320, 240);
7569 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7570 fill_surface(backbuffer3, 0xff00ff00);
7572 hr = IDirectDrawSurface4_Flip(frontbuffer, NULL, DDFLIP_WAIT);
7573 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
7574 color = get_surface_color(backbuffer1, 320, 240);
7575 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
7576 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7577 color = get_surface_color(backbuffer2, 320, 240);
7578 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7579 fill_surface(backbuffer3, 0xff0000ff);
7581 hr = IDirectDrawSurface4_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
7582 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
7583 color = get_surface_color(backbuffer2, 320, 240);
7584 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
7585 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7586 color = get_surface_color(backbuffer3, 320, 240);
7587 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7588 fill_surface(backbuffer1, 0xffff0000);
7590 hr = IDirectDrawSurface4_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
7591 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
7592 color = get_surface_color(backbuffer1, 320, 240);
7593 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7594 color = get_surface_color(backbuffer3, 320, 240);
7595 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
7596 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7597 fill_surface(backbuffer2, 0xff00ff00);
7599 hr = IDirectDrawSurface4_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
7600 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#lx.\n", test_data[i].name, hr);
7601 color = get_surface_color(backbuffer1, 320, 240);
7602 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
7603 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7604 color = get_surface_color(backbuffer2, 320, 240);
7605 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7607 IDirectDrawSurface4_Release(backbuffer3);
7608 IDirectDrawSurface4_Release(backbuffer2);
7609 IDirectDrawSurface4_Release(backbuffer1);
7610 IDirectDrawSurface4_Release(frontbuffer);
7613 refcount = IDirectDraw4_Release(ddraw);
7614 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
7615 DestroyWindow(window);
7618 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
7620 memset(ddsd, 0, sizeof(*ddsd));
7621 ddsd->dwSize = sizeof(*ddsd);
7624 static void test_set_surface_desc(void)
7626 IDirectDraw4 *ddraw;
7627 HWND window;
7628 HRESULT hr;
7629 DDSURFACEDESC2 ddsd;
7630 IDirectDrawSurface4 *surface;
7631 BYTE data[16*16*4];
7632 ULONG ref;
7633 unsigned int i;
7634 static const struct
7636 DWORD caps, caps2;
7637 BOOL supported;
7638 const char *name;
7640 invalid_caps_tests[] =
7642 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
7643 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
7644 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
7645 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
7646 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
7649 window = create_window();
7650 ddraw = create_ddraw();
7651 ok(!!ddraw, "Failed to create a ddraw object.\n");
7652 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7653 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
7655 reset_ddsd(&ddsd);
7656 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
7657 ddsd.dwWidth = 8;
7658 ddsd.dwHeight = 8;
7659 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7660 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7661 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7662 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7663 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7664 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7665 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7667 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
7668 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
7670 reset_ddsd(&ddsd);
7671 ddsd.dwFlags = DDSD_LPSURFACE;
7672 ddsd.lpSurface = data;
7673 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7674 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
7676 /* Redundantly setting the same lpSurface is not an error. */
7677 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7678 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
7679 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
7680 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
7681 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
7682 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
7684 hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, 0, NULL);
7685 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
7686 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
7687 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
7688 hr = IDirectDrawSurface4_Unlock(surface, NULL);
7689 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
7691 reset_ddsd(&ddsd);
7692 ddsd.dwFlags = DDSD_LPSURFACE;
7693 ddsd.lpSurface = data;
7694 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 1);
7695 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7697 ddsd.lpSurface = NULL;
7698 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7699 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7701 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, NULL, 0);
7702 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7704 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
7705 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
7706 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
7707 "Got unexpected caps %#lx.\n", ddsd.ddsCaps.dwCaps);
7708 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#lx.\n", ddsd.ddsCaps.dwCaps2);
7710 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
7711 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7712 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7714 ddsd.dwFlags = DDSD_CAPS;
7715 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7716 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7718 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
7719 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
7720 ddsd.lpSurface = data;
7721 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7722 ok(hr == DDERR_INVALIDCAPS, "Got hr %#lx.\n", hr);
7723 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7724 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7725 ok(hr == DDERR_INVALIDCAPS, "Got hr %#lx.\n", hr);
7726 ddsd.ddsCaps.dwCaps = 0;
7727 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
7728 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7729 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
7731 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
7732 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
7733 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
7734 "Got unexpected caps %#lx.\n", ddsd.ddsCaps.dwCaps);
7735 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#lx.\n", ddsd.ddsCaps.dwCaps2);
7737 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
7738 reset_ddsd(&ddsd);
7739 ddsd.dwFlags = DDSD_HEIGHT;
7740 ddsd.dwHeight = 16;
7741 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7742 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7744 ddsd.lpSurface = data;
7745 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
7746 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7747 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
7749 ddsd.dwHeight = 0;
7750 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7751 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7753 reset_ddsd(&ddsd);
7754 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
7755 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#lx.\n", hr);
7756 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %lu.\n", ddsd.dwWidth);
7757 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %lu.\n", ddsd.dwHeight);
7759 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0 */
7760 reset_ddsd(&ddsd);
7761 ddsd.dwFlags = DDSD_PITCH;
7762 U1(ddsd).lPitch = 8 * 4;
7763 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7764 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7766 ddsd.dwFlags = DDSD_WIDTH;
7767 ddsd.dwWidth = 16;
7768 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7769 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7771 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
7772 ddsd.lpSurface = data;
7773 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7774 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7776 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
7777 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7778 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7780 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7781 U1(ddsd).lPitch = 16 * 4;
7782 ddsd.dwWidth = 16;
7783 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7784 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
7786 reset_ddsd(&ddsd);
7787 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &ddsd);
7788 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
7789 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %lu.\n", ddsd.dwWidth);
7790 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %lu.\n", ddsd.dwHeight);
7791 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %lu.\n", U1(ddsd).lPitch);
7793 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
7795 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
7796 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7797 U1(ddsd).lPitch = 4 * 4;
7798 ddsd.lpSurface = data;
7799 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7800 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#lx.\n", hr);
7802 U1(ddsd).lPitch = 4;
7803 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7804 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#lx.\n", hr);
7806 U1(ddsd).lPitch = 16 * 4 + 1;
7807 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7808 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7810 U1(ddsd).lPitch = 16 * 4 + 3;
7811 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7812 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7814 U1(ddsd).lPitch = -4;
7815 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7816 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7818 U1(ddsd).lPitch = 16 * 4;
7819 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7820 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
7822 reset_ddsd(&ddsd);
7823 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7824 U1(ddsd).lPitch = 0;
7825 ddsd.dwWidth = 16;
7826 ddsd.lpSurface = data;
7827 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7828 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7830 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7831 U1(ddsd).lPitch = 16 * 4;
7832 ddsd.dwWidth = 0;
7833 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7834 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7836 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
7837 ddsd.dwFlags = DDSD_PIXELFORMAT;
7838 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7839 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7840 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7841 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7842 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7843 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7844 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7845 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7847 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
7848 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7849 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
7851 /* Can't set color keys. */
7852 reset_ddsd(&ddsd);
7853 ddsd.dwFlags = DDSD_CKSRCBLT;
7854 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
7855 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
7856 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7857 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7859 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
7860 ddsd.lpSurface = data;
7861 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7862 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
7864 IDirectDrawSurface4_Release(surface);
7866 /* Test mipmap texture. */
7867 reset_ddsd(&ddsd);
7868 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
7869 ddsd.dwWidth = 8;
7870 ddsd.dwHeight = 8;
7871 U2(ddsd).dwMipMapCount = 3;
7872 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7874 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
7875 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW || hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr);
7877 if (FAILED(hr))
7879 skip("Mipmaps are not supported.\n");
7881 else
7883 /* Changing surface desc for mipmap fails even without changing any
7884 * parameters. */
7885 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7886 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#lx.\n", hr);
7888 reset_ddsd(&ddsd);
7889 ddsd.dwFlags = DDSD_LPSURFACE;
7890 ddsd.lpSurface = data;
7891 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7892 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#lx.\n", hr);
7893 IDirectDrawSurface4_Release(surface);
7896 reset_ddsd(&ddsd);
7897 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
7898 ddsd.dwWidth = 8;
7899 ddsd.dwHeight = 8;
7900 U2(ddsd).dwMipMapCount = 3;
7901 ddsd.lpSurface = data;
7902 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7904 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
7905 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW || hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr);
7907 if (hr == DD_OK)
7909 static DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
7910 IDirectDrawSurface4 *surface2;
7912 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &surface2);
7913 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
7914 reset_ddsd(&ddsd);
7915 hr = IDirectDrawSurface4_GetSurfaceDesc(surface2, &ddsd);
7916 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
7917 ok(ddsd.dwWidth == 4, "Got unexpected dwWidth %lu.\n", ddsd.dwWidth);
7919 reset_ddsd(&ddsd);
7920 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
7921 ddsd.dwWidth = 16;
7922 ddsd.dwHeight = 16;
7923 U1(ddsd).lPitch = 16 * 4;
7924 ddsd.lpSurface = data;
7925 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7926 todo_wine ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
7928 reset_ddsd(&ddsd);
7929 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
7930 ddsd.dwWidth = 8;
7931 ddsd.dwHeight = 8;
7932 U1(ddsd).lPitch = 8 * 4;
7933 ddsd.lpSurface = data;
7934 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7935 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
7936 if (0)
7938 /* _Lock causes access violation on Windows. */
7939 reset_ddsd(&ddsd);
7940 hr = IDirectDrawSurface4_Lock(surface2, NULL, &ddsd, DDLOCK_WAIT, NULL);
7941 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
7942 IDirectDrawSurface4_Unlock(surface2, NULL);
7945 reset_ddsd(&ddsd);
7946 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
7947 ddsd.dwWidth = 4;
7948 ddsd.dwHeight = 4;
7949 U1(ddsd).lPitch = 4 * 4;
7950 ddsd.lpSurface = data;
7951 hr = IDirectDrawSurface4_SetSurfaceDesc(surface2, &ddsd, 0);
7952 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
7954 reset_ddsd(&ddsd);
7955 /* Does not crash now after setting user memory for the level. */
7956 hr = IDirectDrawSurface4_Lock(surface2, NULL, &ddsd, DDLOCK_WAIT, NULL);
7957 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
7958 ok(ddsd.lpSurface == data, "Got unexpected lpSurface %p.\n", ddsd.lpSurface);
7959 IDirectDrawSurface4_Unlock(surface2, NULL);
7961 reset_ddsd(&ddsd);
7962 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
7963 ddsd.dwWidth = 16;
7964 ddsd.dwHeight = 16;
7965 U1(ddsd).lPitch = 16 * 4;
7966 ddsd.lpSurface = data;
7967 hr = IDirectDrawSurface4_SetSurfaceDesc(surface2, &ddsd, 0);
7968 todo_wine ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
7970 IDirectDrawSurface4_Release(surface2);
7971 IDirectDrawSurface4_Release(surface);
7974 /* Test surface created with DDSD_LPSURFACE. */
7975 reset_ddsd(&ddsd);
7976 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LPSURFACE | DDSD_PITCH;
7977 ddsd.dwWidth = 8;
7978 ddsd.dwHeight = 8;
7979 ddsd.lpSurface = data;
7980 U1(ddsd).lPitch = 8 * 4;
7981 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7982 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
7983 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
7985 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7986 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#lx.\n", hr);
7988 reset_ddsd(&ddsd);
7989 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
7990 ddsd.dwWidth = 8;
7991 ddsd.dwHeight = 8;
7992 /* Cannot reset lpSurface. */
7993 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
7994 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
7996 reset_ddsd(&ddsd);
7997 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_LPSURFACE | DDSD_PITCH;
7998 ddsd.dwWidth = 4;
7999 ddsd.dwHeight = 4;
8000 ddsd.lpSurface = data;
8001 U1(ddsd).lPitch = 8 * 4;
8002 /* Can change the parameters of surface created with DDSD_LPSURFACE. */
8003 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
8004 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8006 IDirectDrawSurface4_Release(surface);
8008 /* SetSurfaceDesc needs systemmemory surfaces.
8010 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
8011 for (i = 0; i < ARRAY_SIZE(invalid_caps_tests); i++)
8013 reset_ddsd(&ddsd);
8014 ddsd.dwFlags = DDSD_CAPS;
8015 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
8016 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
8017 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
8019 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8020 ddsd.dwWidth = 8;
8021 ddsd.dwHeight = 8;
8022 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
8023 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
8024 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
8025 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8026 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8027 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8030 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
8031 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW, "Got unexpected hr %#lx.\n", hr);
8032 if (FAILED(hr))
8034 skip("Cannot create a %s surface, skipping vidmem SetSurfaceDesc test.\n",
8035 invalid_caps_tests[i].name);
8036 goto done;
8039 reset_ddsd(&ddsd);
8040 ddsd.dwFlags = DDSD_LPSURFACE;
8041 ddsd.lpSurface = data;
8042 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
8043 if (invalid_caps_tests[i].supported)
8045 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8047 else
8049 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#lx.\n",
8050 invalid_caps_tests[i].name, hr);
8052 /* Check priority of error conditions. */
8053 ddsd.dwFlags = DDSD_WIDTH;
8054 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
8055 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#lx.\n",
8056 invalid_caps_tests[i].name, hr);
8059 IDirectDrawSurface4_Release(surface);
8062 done:
8063 ref = IDirectDraw4_Release(ddraw);
8064 ok(!ref, "Unexpected refcount %lu.\n", ref);
8065 DestroyWindow(window);
8068 static void test_user_memory_getdc(void)
8070 unsigned int data[16][16], x, y;
8071 IDirectDraw4 *ddraw;
8072 HWND window;
8073 HRESULT hr;
8074 DDSURFACEDESC2 ddsd;
8075 IDirectDrawSurface4 *surface;
8076 HBITMAP bitmap;
8077 DIBSECTION dib;
8078 ULONG ref;
8079 int size;
8080 HDC dc;
8082 window = create_window();
8083 ddraw = create_ddraw();
8084 ok(!!ddraw, "Failed to create a ddraw object.\n");
8086 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8087 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
8089 reset_ddsd(&ddsd);
8090 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
8091 ddsd.dwWidth = 16;
8092 ddsd.dwHeight = 16;
8093 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
8094 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
8095 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
8096 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8097 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8098 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8099 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
8100 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
8101 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8103 memset(data, 0xaa, sizeof(data));
8104 reset_ddsd(&ddsd);
8105 ddsd.dwFlags = DDSD_LPSURFACE;
8106 ddsd.lpSurface = data;
8107 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
8108 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
8110 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8111 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
8112 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
8113 ok(!!bitmap, "Failed to get bitmap.\n");
8114 size = GetObjectA(bitmap, sizeof(dib), &dib);
8115 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
8116 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
8117 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
8118 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
8119 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8120 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
8122 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
8123 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
8125 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
8126 ddsd.lpSurface = data;
8127 ddsd.dwWidth = 4;
8128 ddsd.dwHeight = 8;
8129 U1(ddsd).lPitch = sizeof(*data);
8130 hr = IDirectDrawSurface4_SetSurfaceDesc(surface, &ddsd, 0);
8131 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#lx.\n", hr);
8133 memset(data, 0xaa, sizeof(data));
8134 hr = IDirectDrawSurface4_GetDC(surface, &dc);
8135 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
8136 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
8137 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
8138 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
8139 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
8141 for (y = 0; y < 4; y++)
8143 for (x = 0; x < 4; x++)
8145 if ((x == 1 || x == 2) && (y == 1 || y == 2))
8146 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
8147 x, y, data[y][x]);
8148 else
8149 ok(data[y][x] == 0x00000000, "Expected color 0x00000000 on position %ux%u, got %#x.\n",
8150 x, y, data[y][x]);
8153 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
8154 data[0][5]);
8155 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
8156 data[7][3]);
8157 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
8158 data[7][4]);
8159 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
8160 data[8][0]);
8162 IDirectDrawSurface4_Release(surface);
8163 ref = IDirectDraw4_Release(ddraw);
8164 ok(!ref, "Unexpected refcount %lu.\n", ref);
8165 DestroyWindow(window);
8168 static void test_sysmem_overlay(void)
8170 IDirectDraw4 *ddraw;
8171 HWND window;
8172 HRESULT hr;
8173 DDSURFACEDESC2 ddsd;
8174 IDirectDrawSurface4 *surface;
8175 ULONG ref;
8177 window = create_window();
8178 ddraw = create_ddraw();
8179 ok(!!ddraw, "Failed to create a ddraw object.\n");
8181 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8182 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
8184 reset_ddsd(&ddsd);
8185 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
8186 ddsd.dwWidth = 16;
8187 ddsd.dwHeight = 16;
8188 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
8189 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
8190 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
8191 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
8192 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8193 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8194 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8195 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
8196 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#lx.\n", hr);
8198 ref = IDirectDraw4_Release(ddraw);
8199 ok(!ref, "Unexpected refcount %lu.\n", ref);
8200 DestroyWindow(window);
8203 static void test_primary_palette(void)
8205 DDSCAPS2 surface_caps = {DDSCAPS_FLIP, 0, 0, {0}};
8206 IDirectDrawSurface4 *primary, *backbuffer;
8207 PALETTEENTRY palette_entries[256];
8208 IDirectDrawPalette *palette, *tmp;
8209 DDSURFACEDESC2 surface_desc;
8210 IDirectDraw4 *ddraw;
8211 DWORD palette_caps;
8212 ULONG refcount;
8213 HWND window;
8214 HRESULT hr;
8216 window = create_window();
8217 ddraw = create_ddraw();
8218 ok(!!ddraw, "Failed to create a ddraw object.\n");
8219 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8221 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8222 IDirectDraw4_Release(ddraw);
8223 DestroyWindow(window);
8224 return;
8226 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8227 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
8229 memset(&surface_desc, 0, sizeof(surface_desc));
8230 surface_desc.dwSize = sizeof(surface_desc);
8231 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8232 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8233 U5(surface_desc).dwBackBufferCount = 1;
8234 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8235 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8236 hr = IDirectDrawSurface4_GetAttachedSurface(primary, &surface_caps, &backbuffer);
8237 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#lx.\n", hr);
8239 memset(palette_entries, 0, sizeof(palette_entries));
8240 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
8241 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
8242 refcount = get_refcount((IUnknown *)palette);
8243 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
8245 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
8246 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#lx.\n", hr);
8247 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#lx.\n", palette_caps);
8249 hr = IDirectDrawSurface4_SetPalette(primary, palette);
8250 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
8252 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
8253 * and is generally somewhat broken with respect to 8 bpp / palette
8254 * handling. */
8255 if (SUCCEEDED(IDirectDrawSurface4_GetPalette(backbuffer, &tmp)))
8257 win_skip("Broken palette handling detected, skipping tests.\n");
8258 IDirectDrawPalette_Release(tmp);
8259 IDirectDrawPalette_Release(palette);
8260 /* The Windows 8 testbot keeps extra references to the primary and
8261 * backbuffer while in 8 bpp mode. */
8262 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
8263 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#lx.\n", hr);
8264 goto done;
8267 refcount = get_refcount((IUnknown *)palette);
8268 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
8270 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
8271 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#lx.\n", hr);
8272 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
8273 "Got unexpected palette caps %#lx.\n", palette_caps);
8275 hr = IDirectDrawSurface4_SetPalette(primary, NULL);
8276 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
8277 refcount = get_refcount((IUnknown *)palette);
8278 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
8280 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
8281 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#lx.\n", hr);
8282 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#lx.\n", palette_caps);
8284 hr = IDirectDrawSurface4_SetPalette(primary, palette);
8285 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
8286 refcount = get_refcount((IUnknown *)palette);
8287 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
8289 hr = IDirectDrawSurface4_GetPalette(primary, &tmp);
8290 ok(SUCCEEDED(hr), "Failed to get palette, hr %#lx.\n", hr);
8291 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
8292 IDirectDrawPalette_Release(tmp);
8293 hr = IDirectDrawSurface4_GetPalette(backbuffer, &tmp);
8294 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#lx.\n", hr);
8296 refcount = IDirectDrawPalette_Release(palette);
8297 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
8298 refcount = IDirectDrawPalette_Release(palette);
8299 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8301 /* Note that this only seems to work when the palette is attached to the
8302 * primary surface. When attached to a regular surface, attempting to get
8303 * the palette here will cause an access violation. */
8304 hr = IDirectDrawSurface4_GetPalette(primary, &tmp);
8305 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#lx.\n", hr);
8307 hr = IDirectDrawSurface4_IsLost(primary);
8308 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
8310 memset(&surface_desc, 0, sizeof(surface_desc));
8311 surface_desc.dwSize = sizeof(surface_desc);
8312 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &surface_desc);
8313 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
8314 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %lu.\n", surface_desc.dwWidth);
8315 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %lu.\n", surface_desc.dwHeight);
8316 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 8, "Got unexpected bit count %lu.\n",
8317 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
8319 hr = set_display_mode(ddraw, 640, 480);
8320 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
8322 memset(&surface_desc, 0, sizeof(surface_desc));
8323 surface_desc.dwSize = sizeof(surface_desc);
8324 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &surface_desc);
8325 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
8326 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %lu.\n", surface_desc.dwWidth);
8327 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %lu.\n", surface_desc.dwHeight);
8328 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
8329 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
8330 "Got unexpected bit count %lu.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
8332 hr = IDirectDrawSurface4_IsLost(primary);
8333 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8334 hr = IDirectDrawSurface4_Restore(primary);
8335 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
8336 hr = IDirectDrawSurface4_IsLost(primary);
8337 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
8339 memset(&surface_desc, 0, sizeof(surface_desc));
8340 surface_desc.dwSize = sizeof(surface_desc);
8341 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &surface_desc);
8342 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
8343 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %lu.\n", surface_desc.dwWidth);
8344 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %lu.\n", surface_desc.dwHeight);
8345 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
8346 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
8347 "Got unexpected bit count %lu.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
8349 done:
8350 refcount = IDirectDrawSurface4_Release(backbuffer);
8351 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
8352 refcount = IDirectDrawSurface4_Release(primary);
8353 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8354 refcount = IDirectDraw4_Release(ddraw);
8355 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8356 DestroyWindow(window);
8359 static HRESULT WINAPI surface_counter(IDirectDrawSurface4 *surface, DDSURFACEDESC2 *desc, void *context)
8361 UINT *surface_count = context;
8363 ++(*surface_count);
8364 IDirectDrawSurface_Release(surface);
8366 return DDENUMRET_OK;
8369 static void test_surface_attachment(void)
8371 IDirectDrawSurface4 *surface1, *surface2, *surface3, *surface4;
8372 IDirectDrawSurface *surface1v1, *surface2v1;
8373 DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
8374 DDSURFACEDESC2 surface_desc;
8375 IDirectDraw4 *ddraw;
8376 UINT surface_count;
8377 ULONG refcount;
8378 HWND window;
8379 HRESULT hr;
8381 window = create_window();
8382 ddraw = create_ddraw();
8383 ok(!!ddraw, "Failed to create a ddraw object.\n");
8384 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8385 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
8387 memset(&surface_desc, 0, sizeof(surface_desc));
8388 surface_desc.dwSize = sizeof(surface_desc);
8389 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
8390 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8391 U2(surface_desc).dwMipMapCount = 3;
8392 surface_desc.dwWidth = 128;
8393 surface_desc.dwHeight = 128;
8394 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
8395 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8397 hr = IDirectDrawSurface4_GetAttachedSurface(surface1, &caps, &surface2);
8398 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#lx.\n", hr);
8399 hr = IDirectDrawSurface4_GetAttachedSurface(surface2, &caps, &surface3);
8400 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#lx.\n", hr);
8401 hr = IDirectDrawSurface4_GetAttachedSurface(surface3, &caps, &surface4);
8402 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
8404 surface_count = 0;
8405 IDirectDrawSurface4_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
8406 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
8407 surface_count = 0;
8408 IDirectDrawSurface4_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
8409 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
8410 surface_count = 0;
8411 IDirectDrawSurface4_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
8412 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
8414 memset(&surface_desc, 0, sizeof(surface_desc));
8415 surface_desc.dwSize = sizeof(surface_desc);
8416 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8417 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8418 surface_desc.dwWidth = 16;
8419 surface_desc.dwHeight = 16;
8420 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
8421 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8423 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4);
8424 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8425 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
8426 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8427 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface4);
8428 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8429 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface3);
8430 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8431 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface4);
8432 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8433 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface2);
8434 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8436 IDirectDrawSurface4_Release(surface4);
8438 memset(&surface_desc, 0, sizeof(surface_desc));
8439 surface_desc.dwSize = sizeof(surface_desc);
8440 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8441 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
8442 surface_desc.dwWidth = 16;
8443 surface_desc.dwHeight = 16;
8444 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
8445 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8447 if (SUCCEEDED(hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4)))
8449 skip("Running on refrast, skipping some tests.\n");
8450 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface4);
8451 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
8453 else
8455 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8456 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
8457 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8458 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface4);
8459 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8460 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface3);
8461 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8462 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface4);
8463 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8464 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface2);
8465 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8468 IDirectDrawSurface4_Release(surface4);
8469 IDirectDrawSurface4_Release(surface3);
8470 IDirectDrawSurface4_Release(surface2);
8471 IDirectDrawSurface4_Release(surface1);
8473 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8474 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
8476 /* Try a single primary and two offscreen plain surfaces. */
8477 memset(&surface_desc, 0, sizeof(surface_desc));
8478 surface_desc.dwSize = sizeof(surface_desc);
8479 surface_desc.dwFlags = DDSD_CAPS;
8480 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8481 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
8482 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8484 memset(&surface_desc, 0, sizeof(surface_desc));
8485 surface_desc.dwSize = sizeof(surface_desc);
8486 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8487 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8488 surface_desc.dwWidth = registry_mode.dmPelsWidth;
8489 surface_desc.dwHeight = registry_mode.dmPelsHeight;
8490 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
8491 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8493 memset(&surface_desc, 0, sizeof(surface_desc));
8494 surface_desc.dwSize = sizeof(surface_desc);
8495 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8496 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8497 surface_desc.dwWidth = registry_mode.dmPelsWidth;
8498 surface_desc.dwHeight = registry_mode.dmPelsHeight;
8499 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
8500 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8502 /* This one has a different size. */
8503 memset(&surface_desc, 0, sizeof(surface_desc));
8504 surface_desc.dwSize = sizeof(surface_desc);
8505 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8506 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8507 surface_desc.dwWidth = 128;
8508 surface_desc.dwHeight = 128;
8509 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
8510 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8512 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
8513 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
8514 /* Try the reverse without detaching first. */
8515 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface1);
8516 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#lx.\n", hr);
8517 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
8518 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
8520 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface1);
8521 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
8522 /* Try to detach reversed. */
8523 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
8524 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8525 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface2, 0, surface1);
8526 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
8528 hr = IDirectDrawSurface4_AddAttachedSurface(surface2, surface3);
8529 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
8530 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface2, 0, surface3);
8531 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
8533 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface4);
8534 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8535 hr = IDirectDrawSurface4_AddAttachedSurface(surface4, surface1);
8536 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8538 IDirectDrawSurface4_Release(surface4);
8539 IDirectDrawSurface4_Release(surface3);
8540 IDirectDrawSurface4_Release(surface2);
8541 IDirectDrawSurface4_Release(surface1);
8543 /* Test depth surfaces of different sizes. */
8544 memset(&surface_desc, 0, sizeof(surface_desc));
8545 surface_desc.dwSize = sizeof(surface_desc);
8546 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8547 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
8548 surface_desc.dwWidth = 64;
8549 surface_desc.dwHeight = 64;
8550 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
8551 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
8553 memset(&surface_desc, 0, sizeof(surface_desc));
8554 surface_desc.dwSize = sizeof(surface_desc);
8555 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
8556 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
8557 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8558 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
8559 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
8560 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
8561 surface_desc.dwWidth = 32;
8562 surface_desc.dwHeight = 32;
8563 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
8564 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
8565 surface_desc.dwWidth = 64;
8566 surface_desc.dwHeight = 64;
8567 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
8568 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
8569 surface_desc.dwWidth = 128;
8570 surface_desc.dwHeight = 128;
8571 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
8572 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
8574 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
8575 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8576 if (SUCCEEDED(hr))
8577 IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
8578 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface3);
8579 ok(hr == D3D_OK, "Failed to attach depth buffer, hr %#lx.\n", hr);
8580 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface3);
8581 ok(hr == D3D_OK, "Failed to detach depth buffer, hr %#lx.\n", hr);
8582 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
8583 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8585 IDirectDrawSurface4_Release(surface4);
8586 IDirectDrawSurface4_Release(surface3);
8587 IDirectDrawSurface4_Release(surface2);
8588 IDirectDrawSurface4_Release(surface1);
8590 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
8591 memset(&surface_desc, 0, sizeof(surface_desc));
8592 surface_desc.dwSize = sizeof(surface_desc);
8593 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8594 surface_desc.dwWidth = 64;
8595 surface_desc.dwHeight = 64;
8596 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
8597 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8598 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
8599 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
8600 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
8601 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
8602 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
8603 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
8604 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8605 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
8606 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8608 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
8609 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
8610 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
8611 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
8612 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
8613 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8615 hr = IDirectDrawSurface4_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
8616 ok(SUCCEEDED(hr), "Failed to get interface, hr %#lx.\n", hr);
8617 hr = IDirectDrawSurface4_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
8618 ok(SUCCEEDED(hr), "Failed to get interface, hr %#lx.\n", hr);
8620 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
8621 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
8622 refcount = get_refcount((IUnknown *)surface2);
8623 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
8624 refcount = get_refcount((IUnknown *)surface2v1);
8625 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
8626 hr = IDirectDrawSurface4_AddAttachedSurface(surface1, surface2);
8627 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#lx.\n", hr);
8628 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
8629 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#lx.\n", hr);
8630 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
8631 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#lx.\n", hr);
8633 /* Attaching while already attached to other surface. */
8634 hr = IDirectDrawSurface4_AddAttachedSurface(surface3, surface2);
8635 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
8636 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface3, 0, surface2);
8637 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
8638 IDirectDrawSurface4_Release(surface3);
8640 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
8641 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
8642 refcount = get_refcount((IUnknown *)surface2);
8643 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
8644 refcount = get_refcount((IUnknown *)surface2v1);
8645 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
8647 /* DeleteAttachedSurface() when attaching via IDirectDrawSurface. */
8648 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
8649 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
8650 hr = IDirectDrawSurface4_DeleteAttachedSurface(surface1, 0, surface2);
8651 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#lx.\n", hr);
8652 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
8653 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx.\n", hr);
8654 refcount = IDirectDrawSurface4_Release(surface2);
8655 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8656 refcount = IDirectDrawSurface4_Release(surface1);
8657 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8659 /* Automatic detachment on release. */
8660 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
8661 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#lx.\n", hr);
8662 refcount = get_refcount((IUnknown *)surface2v1);
8663 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
8664 refcount = IDirectDrawSurface_Release(surface1v1);
8665 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8666 refcount = IDirectDrawSurface_Release(surface2v1);
8667 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8668 refcount = IDirectDraw4_Release(ddraw);
8669 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8670 DestroyWindow(window);
8673 static void test_private_data(void)
8675 IDirectDraw4 *ddraw;
8676 IDirectDrawSurface4 *surface, *surface2;
8677 DDSURFACEDESC2 surface_desc;
8678 ULONG refcount, refcount2, refcount3;
8679 IUnknown *ptr;
8680 DWORD size = sizeof(ptr);
8681 HRESULT hr;
8682 HWND window;
8683 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8684 DWORD data[] = {1, 2, 3, 4};
8685 DDCAPS hal_caps;
8686 static const GUID ddraw_private_data_test_guid =
8688 0xfdb37466,
8689 0x428f,
8690 0x4edf,
8691 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
8693 static const GUID ddraw_private_data_test_guid2 =
8695 0x2e5afac2,
8696 0x87b5,
8697 0x4c10,
8698 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
8701 window = create_window();
8702 ddraw = create_ddraw();
8703 ok(!!ddraw, "Failed to create a ddraw object.\n");
8704 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8705 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
8707 reset_ddsd(&surface_desc);
8708 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
8709 surface_desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
8710 surface_desc.dwHeight = 4;
8711 surface_desc.dwWidth = 4;
8712 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8713 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8715 /* NULL pointers are not valid, but don't cause a crash. */
8716 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL,
8717 sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
8718 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
8719 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 0, 0);
8720 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
8721 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 1, 0);
8722 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
8724 /* DDSPD_IUNKNOWNPOINTER needs sizeof(IUnknown *) bytes of data. */
8725 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8726 0, DDSPD_IUNKNOWNPOINTER);
8727 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
8728 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8729 5, DDSPD_IUNKNOWNPOINTER);
8730 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
8731 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8732 sizeof(ddraw) * 2, DDSPD_IUNKNOWNPOINTER);
8733 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
8735 /* Note that with a size != 0 and size != sizeof(IUnknown *) and
8736 * DDSPD_IUNKNOWNPOINTER set SetPrivateData in ddraw4 and ddraw7
8737 * erases the old content and returns an error. This behavior has
8738 * been fixed in d3d8 and d3d9. Unless an application is found
8739 * that depends on this we don't care about this behavior. */
8740 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8741 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
8742 ok(SUCCEEDED(hr), "Failed to set private data, hr %#lx.\n", hr);
8743 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8744 0, DDSPD_IUNKNOWNPOINTER);
8745 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
8746 size = sizeof(ptr);
8747 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
8748 ok(SUCCEEDED(hr), "Failed to get private data, hr %#lx.\n", hr);
8749 hr = IDirectDrawSurface4_FreePrivateData(surface, &ddraw_private_data_test_guid);
8750 ok(SUCCEEDED(hr), "Failed to free private data, hr %#lx.\n", hr);
8752 refcount = get_refcount((IUnknown *)ddraw);
8753 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8754 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
8755 ok(SUCCEEDED(hr), "Failed to set private data, hr %#lx.\n", hr);
8756 refcount2 = get_refcount((IUnknown *)ddraw);
8757 ok(refcount2 == refcount + 1, "Got unexpected refcount %lu.\n", refcount2);
8759 hr = IDirectDrawSurface4_FreePrivateData(surface, &ddraw_private_data_test_guid);
8760 ok(SUCCEEDED(hr), "Failed to free private data, hr %#lx.\n", hr);
8761 refcount2 = get_refcount((IUnknown *)ddraw);
8762 ok(refcount2 == refcount, "Got unexpected refcount %lu.\n", refcount2);
8764 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8765 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
8766 ok(SUCCEEDED(hr), "Failed to set private data, hr %#lx.\n", hr);
8767 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, surface,
8768 sizeof(surface), DDSPD_IUNKNOWNPOINTER);
8769 ok(SUCCEEDED(hr), "Failed to set private data, hr %#lx.\n", hr);
8770 refcount2 = get_refcount((IUnknown *)ddraw);
8771 ok(refcount2 == refcount, "Got unexpected refcount %lu.\n", refcount2);
8773 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8774 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
8775 ok(SUCCEEDED(hr), "Failed to set private data, hr %#lx.\n", hr);
8776 size = 2 * sizeof(ptr);
8777 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
8778 ok(SUCCEEDED(hr), "Failed to get private data, hr %#lx.\n", hr);
8779 ok(size == sizeof(ddraw), "Got unexpected size %lu.\n", size);
8780 refcount2 = get_refcount(ptr);
8781 /* Object is NOT addref'ed by the getter. */
8782 ok(ptr == (IUnknown *)ddraw, "Returned interface pointer is %p, expected %p.\n", ptr, ddraw);
8783 ok(refcount2 == refcount + 1, "Got unexpected refcount %lu.\n", refcount2);
8785 ptr = (IUnknown *)0xdeadbeef;
8786 size = 1;
8787 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
8788 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#lx.\n", hr);
8789 ok(size == sizeof(ddraw), "Got unexpected size %lu.\n", size);
8790 size = 2 * sizeof(ptr);
8791 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
8792 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
8793 ok(size == 2 * sizeof(ptr), "Got unexpected size %lu.\n", size);
8794 size = 1;
8795 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
8796 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#lx.\n", hr);
8797 ok(size == sizeof(ddraw), "Got unexpected size %lu.\n", size);
8798 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
8799 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid2, NULL, NULL);
8800 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
8801 size = 0xdeadbabe;
8802 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid2, &ptr, &size);
8803 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
8804 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
8805 ok(size == 0xdeadbabe, "Got unexpected size %lu.\n", size);
8806 hr = IDirectDrawSurface4_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, NULL);
8807 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
8809 refcount3 = IDirectDrawSurface4_Release(surface);
8810 ok(!refcount3, "Got unexpected refcount %lu.\n", refcount3);
8812 /* Destroying the surface frees the reference held on the private data. It also frees
8813 * the reference the surface is holding on its creating object. */
8814 refcount2 = get_refcount((IUnknown *)ddraw);
8815 ok(refcount2 == refcount - 1, "Got unexpected refcount %lu.\n", refcount2);
8817 memset(&hal_caps, 0, sizeof(hal_caps));
8818 hal_caps.dwSize = sizeof(hal_caps);
8819 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
8820 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
8821 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
8823 reset_ddsd(&surface_desc);
8824 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT;
8825 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8826 surface_desc.dwHeight = 4;
8827 surface_desc.dwWidth = 4;
8828 U2(surface_desc).dwMipMapCount = 2;
8829 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8830 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8831 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &surface2);
8832 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#lx.\n", hr);
8834 hr = IDirectDrawSurface4_SetPrivateData(surface, &ddraw_private_data_test_guid, data, sizeof(data), 0);
8835 ok(SUCCEEDED(hr), "Failed to set private data, hr %#lx.\n", hr);
8836 hr = IDirectDrawSurface4_GetPrivateData(surface2, &ddraw_private_data_test_guid, NULL, NULL);
8837 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
8839 IDirectDrawSurface4_Release(surface2);
8840 IDirectDrawSurface4_Release(surface);
8842 else
8843 skip("Mipmapped textures not supported, skipping mipmap private data test.\n");
8845 refcount = IDirectDraw4_Release(ddraw);
8846 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
8847 DestroyWindow(window);
8850 static void test_pixel_format(void)
8852 HWND window, window2 = NULL;
8853 HDC hdc, hdc2 = NULL;
8854 HMODULE gl = NULL;
8855 int format, test_format;
8856 PIXELFORMATDESCRIPTOR pfd;
8857 IDirectDraw4 *ddraw = NULL;
8858 IDirectDrawClipper *clipper = NULL;
8859 DDSURFACEDESC2 ddsd;
8860 IDirectDrawSurface4 *primary = NULL, *offscreen;
8861 DDBLTFX fx;
8862 HRESULT hr;
8864 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
8865 100, 100, 160, 160, NULL, NULL, NULL, NULL);
8866 if (!window)
8868 skip("Failed to create window\n");
8869 return;
8872 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
8873 100, 100, 160, 160, NULL, NULL, NULL, NULL);
8875 hdc = GetDC(window);
8876 if (!hdc)
8878 skip("Failed to get DC\n");
8879 goto cleanup;
8882 if (window2)
8883 hdc2 = GetDC(window2);
8885 gl = LoadLibraryA("opengl32.dll");
8886 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
8888 format = GetPixelFormat(hdc);
8889 ok(format == 0, "new window has pixel format %d\n", format);
8891 ZeroMemory(&pfd, sizeof(pfd));
8892 pfd.nSize = sizeof(pfd);
8893 pfd.nVersion = 1;
8894 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
8895 pfd.iPixelType = PFD_TYPE_RGBA;
8896 pfd.iLayerType = PFD_MAIN_PLANE;
8897 format = ChoosePixelFormat(hdc, &pfd);
8898 if (format <= 0)
8900 skip("no pixel format available\n");
8901 goto cleanup;
8904 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
8906 skip("failed to set pixel format\n");
8907 goto cleanup;
8910 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
8912 skip("failed to set pixel format on second window\n");
8913 if (hdc2)
8915 ReleaseDC(window2, hdc2);
8916 hdc2 = NULL;
8920 ddraw = create_ddraw();
8921 ok(!!ddraw, "Failed to create a ddraw object.\n");
8923 test_format = GetPixelFormat(hdc);
8924 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8926 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8927 if (FAILED(hr))
8929 skip("Failed to set cooperative level, hr %#lx.\n", hr);
8930 goto cleanup;
8933 test_format = GetPixelFormat(hdc);
8934 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8936 if (hdc2)
8938 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
8939 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
8940 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
8941 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#lx.\n", hr);
8943 test_format = GetPixelFormat(hdc);
8944 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8946 test_format = GetPixelFormat(hdc2);
8947 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8950 memset(&ddsd, 0, sizeof(ddsd));
8951 ddsd.dwSize = sizeof(ddsd);
8952 ddsd.dwFlags = DDSD_CAPS;
8953 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8955 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
8956 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
8958 test_format = GetPixelFormat(hdc);
8959 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8961 if (hdc2)
8963 test_format = GetPixelFormat(hdc2);
8964 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8967 if (clipper)
8969 hr = IDirectDrawSurface4_SetClipper(primary, clipper);
8970 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
8972 test_format = GetPixelFormat(hdc);
8973 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8975 test_format = GetPixelFormat(hdc2);
8976 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8979 memset(&ddsd, 0, sizeof(ddsd));
8980 ddsd.dwSize = sizeof(ddsd);
8981 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8982 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8983 ddsd.dwWidth = ddsd.dwHeight = 64;
8984 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &offscreen, NULL);
8985 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
8987 memset(&fx, 0, sizeof(fx));
8988 fx.dwSize = sizeof(fx);
8989 hr = IDirectDrawSurface4_Blt(offscreen, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
8990 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#lx.\n", hr);
8992 test_format = GetPixelFormat(hdc);
8993 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8995 hr = IDirectDrawSurface4_Blt(primary, NULL, offscreen, NULL, DDBLT_WAIT, NULL);
8996 ok(SUCCEEDED(hr), "Failed to blit to primary surface, hr %#lx.\n", hr);
8998 test_format = GetPixelFormat(hdc);
8999 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9001 if (hdc2)
9003 test_format = GetPixelFormat(hdc2);
9004 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
9007 IDirectDrawSurface4_Release(offscreen);
9009 cleanup:
9010 if (primary) IDirectDrawSurface4_Release(primary);
9011 if (clipper) IDirectDrawClipper_Release(clipper);
9012 if (ddraw) IDirectDraw4_Release(ddraw);
9013 if (gl) FreeLibrary(gl);
9014 if (hdc) ReleaseDC(window, hdc);
9015 if (hdc2) ReleaseDC(window2, hdc2);
9016 DestroyWindow(window);
9017 if (window2) DestroyWindow(window2);
9020 static void test_create_surface_pitch(void)
9022 DWORD vidmem_total = 0, vidmem_free = 0, vidmem_free2 = 0;
9023 DDSCAPS2 vidmem_caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
9024 IDirectDrawSurface4 * surface, *primary;
9025 DDSURFACEDESC2 surface_desc;
9026 IDirectDraw4 *ddraw;
9027 unsigned int i;
9028 ULONG refcount;
9029 HWND window;
9030 HRESULT hr;
9031 void *mem;
9033 static const struct
9035 DWORD caps;
9036 DWORD flags_in;
9037 DWORD pitch_in;
9038 HRESULT hr;
9039 DWORD flags_out;
9040 DWORD pitch_out32;
9041 DWORD pitch_out64;
9043 test_data[] =
9045 /* 0 */
9046 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
9047 0, 0, DD_OK,
9048 DDSD_PITCH, 0x100, 0x100},
9049 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
9050 DDSD_PITCH, 0x104, DD_OK,
9051 DDSD_PITCH, 0x100, 0x100},
9052 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
9053 DDSD_PITCH, 0x0f8, DD_OK,
9054 DDSD_PITCH, 0x100, 0x100},
9055 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
9056 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
9057 0, 0, 0 },
9058 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
9059 0, 0, DD_OK,
9060 DDSD_PITCH, 0x100, 0x0fc},
9061 /* 5 */
9062 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
9063 DDSD_PITCH, 0x104, DD_OK,
9064 DDSD_PITCH, 0x100, 0x0fc},
9065 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
9066 DDSD_PITCH, 0x0f8, DD_OK,
9067 DDSD_PITCH, 0x100, 0x0fc},
9068 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
9069 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
9070 DDSD_PITCH, 0x100, 0x0fc},
9071 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
9072 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
9073 0, 0, 0 },
9074 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
9075 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
9076 DDSD_PITCH, 0x100, 0x100},
9077 /* 10 */
9078 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
9079 DDSD_LPSURFACE | DDSD_PITCH, 0x0fe, DDERR_INVALIDPARAMS,
9080 0, 0, 0 },
9081 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
9082 DDSD_LPSURFACE | DDSD_PITCH, 0x0fc, DD_OK,
9083 DDSD_PITCH, 0x0fc, 0x0fc},
9084 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
9085 DDSD_LPSURFACE | DDSD_PITCH, 0x0f8, DDERR_INVALIDPARAMS,
9086 0, 0, 0 },
9087 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
9088 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x100, DDERR_INVALIDPARAMS,
9089 0, 0, 0 },
9090 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
9091 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x3f00, DDERR_INVALIDPARAMS,
9092 0, 0, 0 },
9093 /* 15 */
9094 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
9095 DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, 0x100, DD_OK,
9096 DDSD_PITCH, 0x100, 0x100},
9097 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
9098 0, 0, DDERR_INVALIDCAPS,
9099 0, 0, 0 },
9100 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
9101 0, 0, DD_OK,
9102 DDSD_PITCH, 0x100, 0 },
9103 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE,
9104 0, 0, DD_OK,
9105 DDSD_PITCH, 0x100, 0 },
9106 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
9107 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
9108 0, 0, 0 },
9109 /* 20 */
9110 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
9111 0, 0, DDERR_INVALIDCAPS,
9112 0, 0, 0 },
9113 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
9114 0, 0, DD_OK,
9115 DDSD_PITCH, 0x100, 0 },
9116 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
9117 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
9118 DDSD_PITCH, 0x100, 0 },
9120 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
9122 window = create_window();
9123 ddraw = create_ddraw();
9124 ok(!!ddraw, "Failed to create a ddraw object.\n");
9125 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
9126 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
9128 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
9130 /* We need a primary surface and exclusive mode for video memory accounting to work
9131 * right on Windows. Otherwise it gives us junk data, like creating a video memory
9132 * surface freeing up memory. */
9133 memset(&surface_desc, 0, sizeof(surface_desc));
9134 surface_desc.dwSize = sizeof(surface_desc);
9135 surface_desc.dwFlags = DDSD_CAPS;
9136 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
9137 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
9138 ok(SUCCEEDED(hr), "Failed to create a primary surface, hr %#lx.\n", hr);
9140 hr = IDirectDraw4_GetAvailableVidMem(ddraw, &vidmem_caps, &vidmem_total, &vidmem_free);
9141 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW,
9142 "Failed to get available video memory, hr %#lx.\n", hr);
9144 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
9146 memset(&surface_desc, 0, sizeof(surface_desc));
9147 surface_desc.dwSize = sizeof(surface_desc);
9148 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
9149 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
9150 surface_desc.dwWidth = 63;
9151 surface_desc.dwHeight = 63;
9152 U1(surface_desc).lPitch = test_data[i].pitch_in;
9153 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9154 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9155 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9156 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9157 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9158 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9159 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9160 if (test_data[i].flags_in & DDSD_LPSURFACE)
9162 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
9163 ok(hr == expected_hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n", i, hr, expected_hr);
9164 surface_desc.lpSurface = mem;
9165 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9167 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
9168 continue;
9169 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n", i, hr, test_data[i].hr);
9170 if (FAILED(hr))
9171 continue;
9173 memset(&surface_desc, 0, sizeof(surface_desc));
9174 surface_desc.dwSize = sizeof(surface_desc);
9175 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
9176 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#lx.\n", i, hr);
9177 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
9178 "Test %u: Got unexpected flags %#lx, expected %#lx.\n",
9179 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
9180 /* The pitch for textures seems to be implementation specific. */
9181 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
9183 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
9184 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
9185 "Test %u: Got unexpected pitch %#lx, expected %#lx.\n",
9186 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
9187 else
9188 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
9189 "Test %u: Got unexpected pitch %#lx, expected %#lx.\n",
9190 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
9192 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
9194 hr = IDirectDraw4_GetAvailableVidMem(ddraw, &vidmem_caps, &vidmem_total, &vidmem_free2);
9195 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW,
9196 "Failed to get available video memory, hr %#lx.\n", hr);
9197 if (SUCCEEDED(hr) && surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
9199 /* Star Trek Starfleet Academy cares about this bit here: That creating a system memory
9200 * resource does not influence available video memory. */
9201 ok(vidmem_free2 == vidmem_free, "Free video memory changed from %#lx to %#lx, test %u.\n",
9202 vidmem_free, vidmem_free2, i);
9204 else if (SUCCEEDED(hr) && surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
9206 /* DDSCAPS_ALLOCONLOAD does not seem to delay video memory allocation, at least not on
9207 * modern Windows.
9209 * The amount of video memory consumed is different from what dwHeight * lPitch would
9210 * suggest, although not by much. */
9211 ok(vidmem_free2 < vidmem_free,
9212 "Expected free video memory to change, but it did not, test %u.\n", i);
9215 IDirectDrawSurface4_Release(surface);
9217 hr = IDirectDraw4_GetAvailableVidMem(ddraw, &vidmem_caps, &vidmem_total, &vidmem_free2);
9218 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW,
9219 "Failed to get available video memory, hr %#lx.\n", hr);
9220 ok(hr == DDERR_NODIRECTDRAWHW || vidmem_free2 == vidmem_free,
9221 "Free video memory changed from %#lx to %#lx, test %u.\n",
9222 vidmem_free, vidmem_free2, i);
9225 IDirectDrawSurface4_Release(primary);
9226 HeapFree(GetProcessHeap(), 0, mem);
9227 refcount = IDirectDraw4_Release(ddraw);
9228 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
9229 DestroyWindow(window);
9232 static void test_mipmap(void)
9234 IDirectDrawSurface4 *surface, *surface_base, *surface_mip;
9235 unsigned int i, mipmap_count;
9236 DDSURFACEDESC2 surface_desc;
9237 IDirectDraw4 *ddraw;
9238 ULONG refcount;
9239 HWND window;
9240 HRESULT hr;
9241 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
9242 DDCAPS hal_caps;
9244 static const struct
9246 DWORD flags;
9247 DWORD caps;
9248 DWORD width;
9249 DWORD height;
9250 DWORD mipmap_count_in;
9251 HRESULT hr;
9252 DWORD mipmap_count_out;
9254 tests[] =
9256 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
9257 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
9258 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
9259 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
9260 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 6},
9261 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 6},
9264 window = create_window();
9265 ddraw = create_ddraw();
9266 ok(!!ddraw, "Failed to create a ddraw object.\n");
9267 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9268 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
9270 memset(&hal_caps, 0, sizeof(hal_caps));
9271 hal_caps.dwSize = sizeof(hal_caps);
9272 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
9273 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
9274 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
9276 skip("Mipmapped textures not supported, skipping tests.\n");
9277 IDirectDraw4_Release(ddraw);
9278 DestroyWindow(window);
9279 return;
9282 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9284 memset(&surface_desc, 0, sizeof(surface_desc));
9285 surface_desc.dwSize = sizeof(surface_desc);
9286 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
9287 surface_desc.ddsCaps.dwCaps = tests[i].caps;
9288 surface_desc.dwWidth = tests[i].width;
9289 surface_desc.dwHeight = tests[i].height;
9290 if (tests[i].flags & DDSD_MIPMAPCOUNT)
9291 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
9292 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9293 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#lx.\n", i, hr);
9294 if (FAILED(hr))
9295 continue;
9297 memset(&surface_desc, 0, sizeof(surface_desc));
9298 surface_desc.dwSize = sizeof(surface_desc);
9299 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
9300 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#lx.\n", i, hr);
9301 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
9302 "Test %u: Got unexpected flags %#lx.\n", i, surface_desc.dwFlags);
9303 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
9304 "Test %u: Got unexpected mipmap count %lu.\n", i, U2(surface_desc).dwMipMapCount);
9306 surface_base = surface;
9307 IDirectDrawSurface4_AddRef(surface_base);
9308 mipmap_count = U2(surface_desc).dwMipMapCount;
9309 while (mipmap_count > 1)
9311 hr = IDirectDrawSurface4_GetAttachedSurface(surface_base, &caps, &surface_mip);
9312 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get attached surface, hr %#lx.\n", i, mipmap_count, hr);
9314 memset(&surface_desc, 0, sizeof(surface_desc));
9315 surface_desc.dwSize = sizeof(surface_desc);
9316 hr = IDirectDrawSurface4_GetSurfaceDesc(surface_base, &surface_desc);
9317 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get surface desc, hr %#lx.\n", i, mipmap_count, hr);
9318 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
9319 "Test %u, %u: Got unexpected flags %#lx.\n", i, mipmap_count, surface_desc.dwFlags);
9320 ok(U2(surface_desc).dwMipMapCount == mipmap_count,
9321 "Test %u, %u: Got unexpected mipmap count %lu.\n",
9322 i, mipmap_count, U2(surface_desc).dwMipMapCount);
9324 memset(&surface_desc, 0, sizeof(surface_desc));
9325 surface_desc.dwSize = sizeof(surface_desc);
9326 hr = IDirectDrawSurface4_Lock(surface_base, NULL, &surface_desc, 0, NULL);
9327 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#lx.\n", i, mipmap_count, hr);
9328 ok(surface_desc.dwMipMapCount == mipmap_count,
9329 "Test %u, %u: unexpected change of mipmap count %lu.\n",
9330 i, mipmap_count, surface_desc.dwMipMapCount);
9331 memset(&surface_desc, 0, sizeof(surface_desc));
9332 surface_desc.dwSize = sizeof(surface_desc);
9333 hr = IDirectDrawSurface4_Lock(surface_mip, NULL, &surface_desc, 0, NULL);
9334 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#lx.\n", i, mipmap_count, hr);
9335 ok(surface_desc.dwMipMapCount == mipmap_count - 1,
9336 "Test %u, %u: Got unexpected child mipmap count %lu.\n", i, mipmap_count, surface_desc.dwMipMapCount);
9337 IDirectDrawSurface4_Unlock(surface_mip, NULL);
9338 IDirectDrawSurface4_Unlock(surface_base, NULL);
9340 IDirectDrawSurface4_Release(surface_base);
9341 surface_base = surface_mip;
9342 --mipmap_count;
9344 IDirectDrawSurface4_Release(surface_base);
9346 IDirectDrawSurface4_Release(surface);
9349 refcount = IDirectDraw4_Release(ddraw);
9350 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
9351 DestroyWindow(window);
9354 static void test_palette_complex(void)
9356 IDirectDrawSurface4 *surface, *mipmap, *tmp;
9357 DDSURFACEDESC2 surface_desc;
9358 IDirectDraw4 *ddraw;
9359 IDirectDrawPalette *palette, *palette2, *palette_mipmap;
9360 ULONG refcount;
9361 HWND window;
9362 HRESULT hr;
9363 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
9364 DDCAPS hal_caps;
9365 PALETTEENTRY palette_entries[256];
9366 unsigned int i;
9367 HDC dc;
9368 RGBQUAD rgbquad;
9369 UINT count;
9371 window = create_window();
9372 ddraw = create_ddraw();
9373 ok(!!ddraw, "Failed to create a ddraw object.\n");
9374 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9375 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
9377 memset(&hal_caps, 0, sizeof(hal_caps));
9378 hal_caps.dwSize = sizeof(hal_caps);
9379 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
9380 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
9381 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
9383 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
9384 IDirectDraw4_Release(ddraw);
9385 DestroyWindow(window);
9386 return;
9389 memset(&surface_desc, 0, sizeof(surface_desc));
9390 surface_desc.dwSize = sizeof(surface_desc);
9391 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9392 surface_desc.dwWidth = 128;
9393 surface_desc.dwHeight = 128;
9394 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
9395 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9396 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
9397 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
9398 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9399 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9401 memset(palette_entries, 0, sizeof(palette_entries));
9402 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
9403 palette_entries, &palette, NULL);
9404 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
9406 memset(palette_entries, 0, sizeof(palette_entries));
9407 palette_entries[1].peRed = 0xff;
9408 palette_entries[1].peGreen = 0x80;
9409 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
9410 palette_entries, &palette_mipmap, NULL);
9411 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
9413 palette2 = (void *)0xdeadbeef;
9414 hr = IDirectDrawSurface4_GetPalette(surface, &palette2);
9415 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#lx.\n", hr);
9416 ok(!palette2, "Got unexpected palette %p.\n", palette2);
9417 hr = IDirectDrawSurface4_SetPalette(surface, palette);
9418 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
9419 hr = IDirectDrawSurface4_GetPalette(surface, &palette2);
9420 ok(SUCCEEDED(hr), "Failed to get palette, hr %#lx.\n", hr);
9421 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
9422 IDirectDrawPalette_Release(palette2);
9424 mipmap = surface;
9425 IDirectDrawSurface4_AddRef(mipmap);
9426 for (i = 0; i < 7; ++i)
9428 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
9429 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#lx.\n", i, hr);
9430 palette2 = (void *)0xdeadbeef;
9431 hr = IDirectDrawSurface4_GetPalette(tmp, &palette2);
9432 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#lx, i %u.\n", hr, i);
9433 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
9435 hr = IDirectDrawSurface4_SetPalette(tmp, palette_mipmap);
9436 ok(SUCCEEDED(hr), "Failed to set palette, i %u, hr %#lx.\n", i, hr);
9438 hr = IDirectDrawSurface4_GetPalette(tmp, &palette2);
9439 ok(SUCCEEDED(hr), "Failed to get palette, i %u, hr %#lx.\n", i, hr);
9440 ok(palette_mipmap == palette2, "Got unexpected palette %p.\n", palette2);
9441 IDirectDrawPalette_Release(palette2);
9443 hr = IDirectDrawSurface4_GetDC(tmp, &dc);
9444 ok(SUCCEEDED(hr), "Failed to get DC, i %u, hr %#lx.\n", i, hr);
9445 count = GetDIBColorTable(dc, 1, 1, &rgbquad);
9446 ok(count == 1, "Expected count 1, got %u.\n", count);
9447 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x.\n", rgbquad.rgbRed);
9448 ok(rgbquad.rgbGreen == 0x80, "Expected rgbGreen = 0x80, got %#x.\n", rgbquad.rgbGreen);
9449 ok(rgbquad.rgbBlue == 0x0, "Expected rgbBlue = 0x0, got %#x.\n", rgbquad.rgbBlue);
9450 hr = IDirectDrawSurface4_ReleaseDC(tmp, dc);
9451 ok(SUCCEEDED(hr), "Failed to release DC, i %u, hr %#lx.\n", i, hr);
9453 IDirectDrawSurface4_Release(mipmap);
9454 mipmap = tmp;
9457 hr = IDirectDrawSurface4_GetAttachedSurface(mipmap, &caps, &tmp);
9458 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
9459 IDirectDrawSurface4_Release(mipmap);
9460 refcount = IDirectDrawSurface4_Release(surface);
9461 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
9462 refcount = IDirectDrawPalette_Release(palette_mipmap);
9463 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
9464 refcount = IDirectDrawPalette_Release(palette);
9465 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
9467 refcount = IDirectDraw4_Release(ddraw);
9468 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
9469 DestroyWindow(window);
9472 static void test_p8_blit(void)
9474 IDirectDrawSurface4 *src, *dst, *dst_p8;
9475 DDSURFACEDESC2 surface_desc;
9476 unsigned int color, x;
9477 IDirectDraw4 *ddraw;
9478 IDirectDrawPalette *palette, *palette2;
9479 ULONG refcount;
9480 HWND window;
9481 HRESULT hr;
9482 PALETTEENTRY palette_entries[256];
9483 DDBLTFX fx;
9484 BOOL is_warp;
9485 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
9486 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
9487 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
9488 static const unsigned int expected[] =
9490 0x00101010, 0x00010101, 0x00020202, 0x00030303,
9491 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
9494 window = create_window();
9495 ddraw = create_ddraw();
9496 ok(!!ddraw, "Failed to create a ddraw object.\n");
9497 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9498 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
9499 is_warp = ddraw_is_warp(ddraw);
9501 memset(palette_entries, 0, sizeof(palette_entries));
9502 palette_entries[1].peGreen = 0xff;
9503 palette_entries[2].peBlue = 0xff;
9504 palette_entries[3].peFlags = 0xff;
9505 palette_entries[4].peRed = 0xff;
9506 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
9507 palette_entries, &palette, NULL);
9508 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
9509 palette_entries[1].peBlue = 0xff;
9510 palette_entries[2].peGreen = 0xff;
9511 palette_entries[3].peRed = 0xff;
9512 palette_entries[4].peFlags = 0x0;
9513 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
9514 palette_entries, &palette2, NULL);
9515 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
9517 memset(&surface_desc, 0, sizeof(surface_desc));
9518 surface_desc.dwSize = sizeof(surface_desc);
9519 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9520 surface_desc.dwWidth = 8;
9521 surface_desc.dwHeight = 1;
9522 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9523 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9524 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
9525 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
9526 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
9527 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9528 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
9529 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9530 hr = IDirectDrawSurface4_SetPalette(dst_p8, palette2);
9531 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
9533 memset(&surface_desc, 0, sizeof(surface_desc));
9534 surface_desc.dwSize = sizeof(surface_desc);
9535 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9536 surface_desc.dwWidth = 8;
9537 surface_desc.dwHeight = 1;
9538 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9539 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9540 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9541 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9542 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9543 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9544 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9545 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
9546 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
9547 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9549 memset(&surface_desc, 0, sizeof(surface_desc));
9550 surface_desc.dwSize = sizeof(surface_desc);
9551 hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
9552 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#lx.\n", hr);
9553 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
9554 hr = IDirectDrawSurface4_Unlock(src, NULL);
9555 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#lx.\n", hr);
9557 hr = IDirectDrawSurface4_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
9558 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#lx.\n", hr);
9559 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
9560 hr = IDirectDrawSurface4_Unlock(dst_p8, NULL);
9561 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#lx.\n", hr);
9563 fx.dwSize = sizeof(fx);
9564 fx.dwFillColor = 0xdeadbeef;
9565 hr = IDirectDrawSurface4_Blt(dst, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
9566 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
9568 hr = IDirectDrawSurface4_SetPalette(src, palette);
9569 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
9570 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
9571 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
9572 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
9573 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
9574 "Failed to blit, hr %#lx.\n", hr);
9576 if (SUCCEEDED(hr))
9578 for (x = 0; x < ARRAY_SIZE(expected); x++)
9580 color = get_surface_color(dst, x, 0);
9581 /* WARP on 1709 and newer write zeroes on non-colorkeyed P8 -> RGB blits. For ckey
9582 * blits see below. */
9583 todo_wine ok(compare_color(color, expected[x], 0)
9584 || broken(is_warp && compare_color(color, 0x00000000, 0)),
9585 "Pixel %u: Got color %#x, expected %#x.\n",
9586 x, color, expected[x]);
9590 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
9591 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
9592 hr = IDirectDrawSurface4_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
9593 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
9595 hr = IDirectDrawSurface4_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9596 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#lx.\n", hr);
9597 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
9598 * surface untouched. Error checking (DDBLT_KEYSRC without a key
9599 * for example) also works as expected.
9601 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
9602 * the display mode set to P8 doesn't help either. */
9603 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
9604 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
9605 "Got unexpected P8 color key blit result.\n");
9606 hr = IDirectDrawSurface4_Unlock(dst_p8, NULL);
9607 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#lx.\n", hr);
9609 IDirectDrawSurface4_Release(src);
9610 IDirectDrawSurface4_Release(dst);
9611 IDirectDrawSurface4_Release(dst_p8);
9612 IDirectDrawPalette_Release(palette);
9613 IDirectDrawPalette_Release(palette2);
9615 refcount = IDirectDraw4_Release(ddraw);
9616 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
9617 DestroyWindow(window);
9620 static void test_material(void)
9622 D3DMATERIALHANDLE mat_handle, tmp;
9623 IDirect3DMaterial3 *material;
9624 IDirect3DViewport3 *viewport;
9625 IDirect3DDevice3 *device;
9626 IDirectDrawSurface4 *rt;
9627 unsigned int color, i;
9628 ULONG refcount;
9629 HWND window;
9630 HRESULT hr;
9631 BOOL valid;
9633 static struct
9635 struct vec3 position;
9636 struct vec3 normal;
9637 D3DCOLOR diffuse;
9639 quad1[] =
9641 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
9642 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
9643 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
9644 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffffffff},
9646 quad2[] =
9648 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
9649 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
9650 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
9651 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000},
9653 static const struct
9655 void *data;
9656 BOOL material;
9657 D3DCOLOR expected_color;
9659 test_data[] =
9661 {quad1, TRUE, 0x0000ff00},
9662 {quad2, TRUE, 0x0000ff00},
9663 {quad1, FALSE, 0x00ffffff},
9664 {quad2, FALSE, 0x00ff0000},
9666 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
9668 window = create_window();
9669 if (!(device = create_device(window, DDSCL_NORMAL)))
9671 skip("Failed to create a 3D device, skipping test.\n");
9672 DestroyWindow(window);
9673 return;
9676 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
9677 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
9679 viewport = create_viewport(device, 0, 0, 640, 480);
9680 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
9681 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
9683 material = create_emissive_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
9684 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
9685 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#lx.\n", hr);
9687 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
9688 ok(SUCCEEDED(hr), "Failed to get light state, hr %#lx.\n", hr);
9689 ok(!tmp, "Got unexpected material handle %#lx.\n", tmp);
9690 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
9691 ok(SUCCEEDED(hr), "Failed to set material state, hr %#lx.\n", hr);
9692 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
9693 ok(SUCCEEDED(hr), "Failed to get light state, hr %#lx.\n", hr);
9694 ok(tmp == mat_handle, "Got unexpected material handle %#lx, expected %#lx.\n", tmp, mat_handle);
9695 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, 0);
9696 ok(SUCCEEDED(hr), "Failed to set material state, hr %#lx.\n", hr);
9697 hr = IDirect3DDevice3_GetLightState(device, D3DLIGHTSTATE_MATERIAL, &tmp);
9698 ok(SUCCEEDED(hr), "Failed to get light state, hr %#lx.\n", hr);
9699 ok(!tmp, "Got unexpected material handle %#lx.\n", tmp);
9701 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
9703 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
9704 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
9705 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
9707 hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, test_data[i].material ? mat_handle : 0);
9708 ok(SUCCEEDED(hr), "Failed to set material state, hr %#lx.\n", hr);
9710 hr = IDirect3DDevice3_BeginScene(device);
9711 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
9712 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9713 D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE, test_data[i].data, 4, 0);
9714 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
9715 hr = IDirect3DDevice3_EndScene(device);
9716 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
9717 color = get_surface_color(rt, 320, 240);
9718 ok(compare_color(color, test_data[i].expected_color, 1),
9719 "Got unexpected color 0x%08x, test %u.\n", color, i);
9722 destroy_material(material);
9723 material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
9724 hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
9725 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#lx.\n", hr);
9727 hr = IDirect3DViewport3_SetBackground(viewport, mat_handle);
9728 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#lx.\n", hr);
9729 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
9730 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#lx.\n", hr);
9731 ok(tmp == mat_handle, "Got unexpected material handle %#lx, expected %#lx.\n", tmp, mat_handle);
9732 ok(valid, "Got unexpected valid %#x.\n", valid);
9733 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9734 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
9735 color = get_surface_color(rt, 320, 240);
9736 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
9738 hr = IDirect3DViewport3_SetBackground(viewport, 0);
9739 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
9740 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
9741 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#lx.\n", hr);
9742 ok(tmp == mat_handle, "Got unexpected material handle %#lx, expected %#lx.\n", tmp, mat_handle);
9743 ok(valid, "Got unexpected valid %#x.\n", valid);
9744 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9745 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
9746 color = get_surface_color(rt, 320, 240);
9747 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
9749 destroy_viewport(device, viewport);
9750 viewport = create_viewport(device, 0, 0, 640, 480);
9752 hr = IDirect3DViewport3_GetBackground(viewport, &tmp, &valid);
9753 ok(SUCCEEDED(hr), "Failed to get viewport background, hr %#lx.\n", hr);
9754 ok(!tmp, "Got unexpected material handle %#lx.\n", tmp);
9755 ok(!valid, "Got unexpected valid %#x.\n", valid);
9756 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
9757 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
9758 color = get_surface_color(rt, 320, 240);
9759 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x.\n", color);
9761 destroy_viewport(device, viewport);
9762 destroy_material(material);
9763 IDirectDrawSurface4_Release(rt);
9764 refcount = IDirect3DDevice3_Release(device);
9765 ok(!refcount, "Device has %lu references left.\n", refcount);
9766 DestroyWindow(window);
9769 static void test_palette_gdi(void)
9771 IDirectDrawSurface4 *surface, *primary;
9772 DDSURFACEDESC2 surface_desc;
9773 unsigned int color, i;
9774 IDirectDraw4 *ddraw;
9775 IDirectDrawPalette *palette, *palette2;
9776 ULONG refcount;
9777 HWND window;
9778 HRESULT hr;
9779 PALETTEENTRY palette_entries[256];
9780 HDC dc;
9781 DDBLTFX fx;
9782 RECT r;
9784 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
9785 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
9786 * not the point of this test. */
9787 static const RGBQUAD expected1[] =
9789 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
9790 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
9792 static const RGBQUAD expected2[] =
9794 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
9795 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
9797 static const RGBQUAD expected3[] =
9799 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
9800 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
9802 HPALETTE ddraw_palette_handle;
9803 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
9804 RGBQUAD rgbquad[255];
9805 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
9807 window = create_window();
9808 ddraw = create_ddraw();
9809 ok(!!ddraw, "Failed to create a ddraw object.\n");
9810 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9811 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
9813 memset(&surface_desc, 0, sizeof(surface_desc));
9814 surface_desc.dwSize = sizeof(surface_desc);
9815 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9816 surface_desc.dwWidth = 16;
9817 surface_desc.dwHeight = 16;
9818 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9819 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9820 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
9821 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
9822 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9823 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9825 /* Avoid colors from the Windows default palette. */
9826 memset(palette_entries, 0, sizeof(palette_entries));
9827 palette_entries[1].peRed = 0x01;
9828 palette_entries[2].peGreen = 0x02;
9829 palette_entries[3].peBlue = 0x03;
9830 palette_entries[4].peRed = 0x13;
9831 palette_entries[4].peGreen = 0x14;
9832 palette_entries[4].peBlue = 0x15;
9833 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
9834 palette_entries, &palette, NULL);
9835 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
9837 /* If there is no palette assigned and the display mode is not 8 bpp, some
9838 * drivers refuse to create a DC while others allow it. If a DC is created,
9839 * the DIB color table is uninitialized and contains random colors. No error
9840 * is generated when trying to read pixels and random garbage is returned.
9842 * The most likely explanation is that if the driver creates a DC, it (or
9843 * the higher-level runtime) uses GetSystemPaletteEntries to find the
9844 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
9845 * contains uninitialized garbage. See comments below for the P8 case. */
9847 hr = IDirectDrawSurface4_SetPalette(surface, palette);
9848 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
9849 hr = IDirectDrawSurface4_GetDC(surface, &dc);
9850 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
9851 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
9852 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
9853 "Got unexpected palette %p, expected %p.\n",
9854 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
9856 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
9857 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
9858 for (i = 0; i < ARRAY_SIZE(expected1); i++)
9860 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
9861 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9862 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
9863 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
9865 for (; i < ARRAY_SIZE(rgbquad); i++)
9867 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
9868 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
9869 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
9872 /* Update the palette while the DC is in use. This does not modify the DC. */
9873 palette_entries[4].peRed = 0x23;
9874 palette_entries[4].peGreen = 0x24;
9875 palette_entries[4].peBlue = 0x25;
9876 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
9877 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#lx.\n", hr);
9879 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
9880 ok(i == 1, "Expected count 1, got %u.\n", i);
9881 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
9882 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9883 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
9884 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
9886 /* Neither does re-setting the palette. */
9887 hr = IDirectDrawSurface4_SetPalette(surface, NULL);
9888 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
9889 hr = IDirectDrawSurface4_SetPalette(surface, palette);
9890 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
9892 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
9893 ok(i == 1, "Expected count 1, got %u.\n", i);
9894 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
9895 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9896 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
9897 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
9899 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
9900 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
9902 /* Refresh the DC. This updates the palette. */
9903 hr = IDirectDrawSurface4_GetDC(surface, &dc);
9904 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
9905 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
9906 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
9907 for (i = 0; i < ARRAY_SIZE(expected2); i++)
9909 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
9910 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9911 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
9912 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
9914 for (; i < ARRAY_SIZE(rgbquad); i++)
9916 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
9917 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
9918 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
9920 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
9921 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
9923 refcount = IDirectDrawSurface4_Release(surface);
9924 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
9926 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
9927 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
9928 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
9930 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
9931 IDirectDrawPalette_Release(palette);
9932 IDirectDraw4_Release(ddraw);
9933 DestroyWindow(window);
9934 return;
9936 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#lx.\n", hr);
9938 memset(&surface_desc, 0, sizeof(surface_desc));
9939 surface_desc.dwSize = sizeof(surface_desc);
9940 surface_desc.dwFlags = DDSD_CAPS;
9941 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
9942 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
9943 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
9945 memset(&fx, 0, sizeof(fx));
9946 fx.dwSize = sizeof(fx);
9947 U5(fx).dwFillColor = 3;
9948 SetRect(&r, 0, 0, 319, 479);
9949 hr = IDirectDrawSurface4_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9950 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#lx.\n", hr);
9951 SetRect(&r, 320, 0, 639, 479);
9952 U5(fx).dwFillColor = 4;
9953 hr = IDirectDrawSurface4_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9954 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#lx.\n", hr);
9956 hr = IDirectDrawSurface4_SetPalette(primary, palette);
9957 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
9958 hr = IDirectDrawSurface4_GetDC(primary, &dc);
9959 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
9961 color = GetPixel(dc, 160, 240);
9962 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
9963 color = GetPixel(dc, 480, 240);
9964 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
9966 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
9967 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
9968 "Got unexpected palette %p, expected %p.\n",
9969 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
9970 SelectPalette(dc, ddraw_palette_handle, FALSE);
9972 /* The primary uses the system palette. In exclusive mode, the system palette matches
9973 * the ddraw palette attached to the primary, so the result is what you would expect
9974 * from a regular surface. Tests for the interaction between the ddraw palette and
9975 * the system palette are not included pending an application that depends on this.
9976 * The relation between those causes problems on Windows Vista and newer for games
9977 * like Age of Empires or StarCraft. Don't emulate it without a real need. */
9978 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
9979 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
9980 for (i = 0; i < ARRAY_SIZE(expected2); i++)
9982 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
9983 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9984 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
9985 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
9987 for (; i < ARRAY_SIZE(rgbquad); i++)
9989 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
9990 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
9991 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
9993 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
9994 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
9996 memset(&surface_desc, 0, sizeof(surface_desc));
9997 surface_desc.dwSize = sizeof(surface_desc);
9998 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
9999 surface_desc.dwWidth = 16;
10000 surface_desc.dwHeight = 16;
10001 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10002 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10003 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10005 /* Here the offscreen surface appears to use the primary's palette,
10006 * but in all likelihood it is actually the system palette. */
10007 hr = IDirectDrawSurface4_GetDC(surface, &dc);
10008 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
10009 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
10010 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
10011 for (i = 0; i < ARRAY_SIZE(expected2); i++)
10013 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
10014 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
10015 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
10016 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
10018 for (; i < ARRAY_SIZE(rgbquad); i++)
10020 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
10021 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
10022 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
10024 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
10025 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
10027 /* On real hardware a change to the primary surface's palette applies immediately,
10028 * even on device contexts from offscreen surfaces that do not have their own
10029 * palette. On the testbot VMs this is not the case. Don't test this until we
10030 * know of an application that depends on this. */
10032 memset(palette_entries, 0, sizeof(palette_entries));
10033 palette_entries[1].peBlue = 0x40;
10034 palette_entries[2].peRed = 0x40;
10035 palette_entries[3].peGreen = 0x40;
10036 palette_entries[4].peRed = 0x12;
10037 palette_entries[4].peGreen = 0x34;
10038 palette_entries[4].peBlue = 0x56;
10039 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
10040 palette_entries, &palette2, NULL);
10041 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
10042 hr = IDirectDrawSurface4_SetPalette(surface, palette2);
10043 ok(SUCCEEDED(hr), "Failed to set palette, hr %#lx.\n", hr);
10045 /* A palette assigned to the offscreen surface overrides the primary / system
10046 * palette. */
10047 hr = IDirectDrawSurface4_GetDC(surface, &dc);
10048 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
10049 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
10050 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
10051 for (i = 0; i < ARRAY_SIZE(expected3); i++)
10053 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
10054 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
10055 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
10056 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
10058 for (; i < ARRAY_SIZE(rgbquad); i++)
10060 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
10061 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
10062 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
10064 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
10065 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
10067 refcount = IDirectDrawSurface4_Release(surface);
10068 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
10070 /* The Windows 8 testbot keeps extra references to the primary and
10071 * backbuffer while in 8 bpp mode. */
10072 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
10073 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#lx.\n", hr);
10075 refcount = IDirectDrawSurface4_Release(primary);
10076 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
10077 refcount = IDirectDrawPalette_Release(palette2);
10078 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
10079 refcount = IDirectDrawPalette_Release(palette);
10080 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
10081 refcount = IDirectDraw4_Release(ddraw);
10082 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
10083 DestroyWindow(window);
10086 static void test_palette_alpha(void)
10088 IDirectDrawSurface4 *surface;
10089 DDSURFACEDESC2 surface_desc;
10090 IDirectDraw4 *ddraw;
10091 IDirectDrawPalette *palette;
10092 ULONG refcount;
10093 HWND window;
10094 HRESULT hr;
10095 PALETTEENTRY palette_entries[256];
10096 unsigned int i;
10097 static const struct
10099 DWORD caps, flags;
10100 BOOL attach_allowed;
10101 const char *name;
10103 test_data[] =
10105 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
10106 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
10107 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
10110 window = create_window();
10111 ddraw = create_ddraw();
10112 ok(!!ddraw, "Failed to create a ddraw object.\n");
10113 if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
10115 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
10116 IDirectDraw4_Release(ddraw);
10117 DestroyWindow(window);
10118 return;
10120 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
10121 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
10123 memset(palette_entries, 0, sizeof(palette_entries));
10124 palette_entries[1].peFlags = 0x42;
10125 palette_entries[2].peFlags = 0xff;
10126 palette_entries[3].peFlags = 0x80;
10127 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
10128 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
10130 memset(palette_entries, 0x66, sizeof(palette_entries));
10131 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
10132 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#lx.\n", hr);
10133 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
10134 palette_entries[0].peFlags);
10135 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
10136 palette_entries[1].peFlags);
10137 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
10138 palette_entries[2].peFlags);
10139 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
10140 palette_entries[3].peFlags);
10142 IDirectDrawPalette_Release(palette);
10144 memset(palette_entries, 0, sizeof(palette_entries));
10145 palette_entries[1].peFlags = 0x42;
10146 palette_entries[1].peRed = 0xff;
10147 palette_entries[2].peFlags = 0xff;
10148 palette_entries[3].peFlags = 0x80;
10149 hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
10150 palette_entries, &palette, NULL);
10151 ok(SUCCEEDED(hr), "Failed to create palette, hr %#lx.\n", hr);
10153 memset(palette_entries, 0x66, sizeof(palette_entries));
10154 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
10155 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#lx.\n", hr);
10156 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
10157 palette_entries[0].peFlags);
10158 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
10159 palette_entries[1].peFlags);
10160 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
10161 palette_entries[2].peFlags);
10162 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
10163 palette_entries[3].peFlags);
10165 for (i = 0; i < ARRAY_SIZE(test_data); i++)
10167 memset(&surface_desc, 0, sizeof(surface_desc));
10168 surface_desc.dwSize = sizeof(surface_desc);
10169 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
10170 surface_desc.dwWidth = 128;
10171 surface_desc.dwHeight = 128;
10172 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
10173 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10174 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#lx.\n", test_data[i].name, hr);
10176 hr = IDirectDrawSurface4_SetPalette(surface, palette);
10177 if (test_data[i].attach_allowed)
10178 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#lx.\n", test_data[i].name, hr);
10179 else
10180 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#lx, %s surface.\n", hr, test_data[i].name);
10182 if (SUCCEEDED(hr))
10184 HDC dc;
10185 RGBQUAD rgbquad;
10186 UINT retval;
10188 hr = IDirectDrawSurface4_GetDC(surface, &dc);
10189 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx, %s surface.\n", hr, test_data[i].name);
10190 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
10191 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
10192 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
10193 rgbquad.rgbRed, test_data[i].name);
10194 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
10195 rgbquad.rgbGreen, test_data[i].name);
10196 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
10197 rgbquad.rgbBlue, test_data[i].name);
10198 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
10199 rgbquad.rgbReserved, test_data[i].name);
10200 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
10201 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
10203 IDirectDrawSurface4_Release(surface);
10206 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
10207 memset(&surface_desc, 0, sizeof(surface_desc));
10208 surface_desc.dwSize = sizeof(surface_desc);
10209 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10210 surface_desc.dwWidth = 128;
10211 surface_desc.dwHeight = 128;
10212 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10213 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10214 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10215 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10216 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10217 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10218 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10219 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10220 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10221 hr = IDirectDrawSurface4_SetPalette(surface, palette);
10222 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#lx.\n", hr);
10223 IDirectDrawSurface4_Release(surface);
10225 /* The Windows 8 testbot keeps extra references to the primary
10226 * while in 8 bpp mode. */
10227 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
10228 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#lx.\n", hr);
10230 refcount = IDirectDrawPalette_Release(palette);
10231 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
10232 refcount = IDirectDraw4_Release(ddraw);
10233 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
10234 DestroyWindow(window);
10237 static void test_vb_writeonly(void)
10239 IDirect3DDevice3 *device;
10240 IDirect3D3 *d3d;
10241 IDirect3DVertexBuffer *buffer;
10242 HWND window;
10243 HRESULT hr;
10244 D3DVERTEXBUFFERDESC desc;
10245 void *ptr;
10246 static const struct vec4 quad[] =
10248 { 0.0f, 480.0f, 0.0f, 1.0f},
10249 { 0.0f, 0.0f, 0.0f, 1.0f},
10250 {640.0f, 480.0f, 0.0f, 1.0f},
10251 {640.0f, 0.0f, 0.0f, 1.0f},
10254 window = create_window();
10255 if (!(device = create_device(window, DDSCL_NORMAL)))
10257 skip("Failed to create a 3D device, skipping test.\n");
10258 DestroyWindow(window);
10259 return;
10262 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
10263 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
10265 memset(&desc, 0, sizeof(desc));
10266 desc.dwSize = sizeof(desc);
10267 desc.dwCaps = D3DVBCAPS_WRITEONLY;
10268 desc.dwFVF = D3DFVF_XYZRHW;
10269 desc.dwNumVertices = ARRAY_SIZE(quad);
10270 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &buffer, 0, NULL);
10271 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#lx.\n", hr);
10273 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, &ptr, NULL);
10274 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#lx.\n", hr);
10275 memcpy(ptr, quad, sizeof(quad));
10276 hr = IDirect3DVertexBuffer_Unlock(buffer);
10277 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#lx.\n", hr);
10279 hr = IDirect3DDevice3_BeginScene(device);
10280 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
10281 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
10282 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
10283 hr = IDirect3DDevice3_EndScene(device);
10284 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
10286 hr = IDirect3DVertexBuffer_Lock(buffer, 0, &ptr, NULL);
10287 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#lx.\n", hr);
10288 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
10289 hr = IDirect3DVertexBuffer_Unlock(buffer);
10290 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#lx.\n", hr);
10292 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_READONLY, &ptr, NULL);
10293 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#lx.\n", hr);
10294 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
10295 hr = IDirect3DVertexBuffer_Unlock(buffer);
10296 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#lx.\n", hr);
10298 IDirect3DVertexBuffer_Release(buffer);
10299 IDirect3D3_Release(d3d);
10300 IDirect3DDevice3_Release(device);
10301 DestroyWindow(window);
10304 static void test_lost_device(void)
10306 IDirectDrawSurface4 *surface, *back_buffer, *back_buffer2, *ds;
10307 IDirectDrawSurface4 *sysmem_surface, *vidmem_surface;
10308 DDSURFACEDESC2 surface_desc;
10309 HWND window1, window2;
10310 IDirectDraw4 *ddraw;
10311 DDPIXELFORMAT z_fmt;
10312 IDirect3D3 *d3d;
10314 ULONG refcount;
10315 DDSCAPS2 caps;
10316 HRESULT hr;
10317 BOOL ret;
10319 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10320 0, 0, 640, 480, 0, 0, 0, 0);
10321 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10322 0, 0, 640, 480, 0, 0, 0, 0);
10323 ddraw = create_ddraw();
10324 ok(!!ddraw, "Failed to create a ddraw object.\n");
10325 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
10326 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10328 memset(&surface_desc, 0, sizeof(surface_desc));
10329 surface_desc.dwSize = sizeof(surface_desc);
10330 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
10331 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
10332 U5(surface_desc).dwBackBufferCount = 1;
10333 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10334 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10336 memset(&surface_desc, 0, sizeof(surface_desc));
10337 surface_desc.dwSize = sizeof(surface_desc);
10338 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
10339 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10340 surface_desc.dwWidth = 100;
10341 surface_desc.dwHeight = 100;
10342 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
10343 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10345 memset(&surface_desc, 0, sizeof(surface_desc));
10346 surface_desc.dwSize = sizeof(surface_desc);
10347 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10348 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
10349 surface_desc.dwWidth = 64;
10350 surface_desc.dwHeight = 64;
10351 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10352 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10353 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10354 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10355 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10356 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10357 if (FAILED(IDirectDraw4_CreateSurface(ddraw, &surface_desc, &vidmem_surface, NULL)))
10359 skip("Failed to create video memory surface, skipping related tests.\n");
10360 vidmem_surface = NULL;
10363 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10364 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10365 hr = IDirectDrawSurface4_IsLost(surface);
10366 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10367 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
10368 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10369 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10370 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10371 if (vidmem_surface)
10373 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10374 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10377 ret = SetForegroundWindow(GetDesktopWindow());
10378 ok(ret, "Failed to set foreground window.\n");
10379 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10380 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
10381 hr = IDirectDrawSurface4_IsLost(surface);
10382 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10383 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
10384 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10385 hr = IDirectDrawSurface4_Restore(surface);
10386 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
10387 hr = IDirectDrawSurface4_IsLost(surface);
10388 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10389 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10390 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10391 hr = IDirectDrawSurface4_Restore(sysmem_surface);
10392 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10393 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10394 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10395 if (vidmem_surface)
10397 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10398 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10399 hr = IDirectDrawSurface4_Restore(vidmem_surface);
10400 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#lx.\n", hr);
10401 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10402 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10405 ret = SetForegroundWindow(window1);
10406 ok(ret, "Failed to set foreground window.\n");
10407 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10408 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10409 hr = IDirectDrawSurface4_IsLost(surface);
10410 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10411 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
10412 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10413 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10414 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10415 if (vidmem_surface)
10417 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10418 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10421 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
10422 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10423 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10424 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10425 hr = IDirectDrawSurface4_IsLost(surface);
10426 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10427 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
10428 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10429 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10430 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10431 if (vidmem_surface)
10433 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10434 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10437 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
10438 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10439 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10440 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10441 hr = IDirectDrawSurface4_IsLost(surface);
10442 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10443 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
10444 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10445 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10446 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10447 if (vidmem_surface)
10449 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10450 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10453 /* Trying to restore the primary will crash, probably because flippable
10454 * surfaces can't exist in DDSCL_NORMAL. */
10455 IDirectDrawSurface4_Release(surface);
10456 memset(&surface_desc, 0, sizeof(surface_desc));
10457 surface_desc.dwSize = sizeof(surface_desc);
10458 surface_desc.dwFlags = DDSD_CAPS;
10459 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
10460 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10461 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10462 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
10463 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10465 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10466 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10467 hr = IDirectDrawSurface4_IsLost(surface);
10468 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10469 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10470 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10471 if (vidmem_surface)
10473 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10474 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10477 ret = SetForegroundWindow(GetDesktopWindow());
10478 ok(ret, "Failed to set foreground window.\n");
10479 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10480 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10481 hr = IDirectDrawSurface4_IsLost(surface);
10482 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10483 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10484 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10485 if (vidmem_surface)
10487 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10488 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10491 ret = SetForegroundWindow(window1);
10492 ok(ret, "Failed to set foreground window.\n");
10493 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10494 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10495 hr = IDirectDrawSurface4_IsLost(surface);
10496 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10497 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10498 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10499 if (vidmem_surface)
10501 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10502 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10505 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
10506 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10507 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10508 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10509 hr = IDirectDrawSurface4_IsLost(surface);
10510 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10511 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10512 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10513 if (vidmem_surface)
10515 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10516 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10519 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
10520 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10521 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10522 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10523 hr = IDirectDrawSurface4_IsLost(surface);
10524 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10525 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10526 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10527 if (vidmem_surface)
10529 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10530 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10533 IDirectDrawSurface4_Release(surface);
10534 memset(&surface_desc, 0, sizeof(surface_desc));
10535 surface_desc.dwSize = sizeof(surface_desc);
10536 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
10537 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
10538 U5(surface_desc).dwBackBufferCount = 2;
10539 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10540 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10543 ds = NULL;
10544 hr = IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d);
10545 if (hr == S_OK)
10547 memset(&z_fmt, 0, sizeof(z_fmt));
10548 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
10549 if (FAILED(hr) || !z_fmt.dwSize)
10551 skip("No depth buffer formats available, skipping Z buffer restore test.\n");
10553 else
10555 memset(&surface_desc, 0, sizeof(surface_desc));
10556 surface_desc.dwSize = sizeof(surface_desc);
10557 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
10558 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10560 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
10561 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
10562 U4(surface_desc).ddpfPixelFormat = z_fmt;
10563 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
10564 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10566 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
10567 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10569 IDirect3D3_Release(d3d);
10571 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
10572 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10573 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10574 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10575 hr = IDirectDrawSurface4_IsLost(surface);
10576 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10577 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
10578 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10579 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10580 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10581 if (vidmem_surface)
10583 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10584 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10587 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
10588 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10589 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10590 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10591 hr = IDirectDrawSurface4_IsLost(surface);
10592 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10593 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
10594 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
10595 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10596 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10597 if (vidmem_surface)
10599 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10600 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10603 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
10604 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10605 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10606 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10607 hr = IDirectDrawSurface4_IsLost(surface);
10608 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10609 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
10610 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
10611 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10612 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10613 if (vidmem_surface)
10615 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10616 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10619 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
10620 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10621 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10622 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10623 hr = IDirectDrawSurface4_IsLost(surface);
10624 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10625 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
10626 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
10627 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10628 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10629 if (vidmem_surface)
10631 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10632 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10635 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
10636 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10637 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10638 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10639 hr = IDirectDrawSurface4_IsLost(surface);
10640 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10641 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
10642 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#lx.\n", hr);
10643 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10644 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10645 if (vidmem_surface)
10647 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10648 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10651 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
10652 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10653 hr = IDirectDraw4_TestCooperativeLevel(ddraw);
10654 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10655 hr = IDirectDrawSurface4_IsLost(surface);
10656 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10657 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
10658 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10659 if (vidmem_surface)
10661 hr = IDirectDrawSurface4_IsLost(vidmem_surface);
10662 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10665 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
10666 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10668 memset(&caps, 0, sizeof(caps));
10669 caps.dwCaps = DDSCAPS_FLIP;
10671 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &back_buffer);
10672 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10673 hr = IDirectDrawSurface4_Restore(surface);
10674 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10675 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &back_buffer);
10676 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10677 ok(back_buffer != surface, "Got the same surface.\n");
10678 hr = IDirectDrawSurface4_IsLost(back_buffer);
10679 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10680 IDirectDrawSurface4_Release(back_buffer);
10682 hr = IDirectDrawSurface4_GetAttachedSurface(back_buffer, &caps, &back_buffer2);
10683 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10684 ok(back_buffer2 != back_buffer, "Got the same surface.\n");
10685 ok(back_buffer2 != surface, "Got the same surface.\n");
10686 hr = IDirectDrawSurface4_IsLost(back_buffer2);
10687 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10688 IDirectDrawSurface4_Release(back_buffer2);
10690 if (ds)
10692 hr = IDirectDrawSurface4_IsLost(ds);
10693 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#lx.\n", hr);
10694 hr = IDirectDrawSurface4_Restore(ds);
10695 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10696 hr = IDirectDrawSurface4_IsLost(ds);
10697 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
10698 IDirectDrawSurface4_Release(ds);
10701 if (vidmem_surface)
10702 IDirectDrawSurface4_Release(vidmem_surface);
10703 IDirectDrawSurface4_Release(sysmem_surface);
10704 IDirectDrawSurface4_Release(surface);
10705 refcount = IDirectDraw4_Release(ddraw);
10706 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
10707 DestroyWindow(window2);
10708 DestroyWindow(window1);
10711 static void test_surface_desc_lock(void)
10713 IDirectDrawSurface4 *surface;
10714 DDSURFACEDESC2 surface_desc;
10715 IDirectDraw4 *ddraw;
10716 ULONG refcount;
10717 HWND window;
10718 HRESULT hr;
10720 window = create_window();
10721 ddraw = create_ddraw();
10722 ok(!!ddraw, "Failed to create a ddraw object.\n");
10723 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10724 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
10726 memset(&surface_desc, 0, sizeof(surface_desc));
10727 surface_desc.dwSize = sizeof(surface_desc);
10728 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
10729 surface_desc.dwWidth = 16;
10730 surface_desc.dwHeight = 16;
10731 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10732 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10733 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
10735 memset(&surface_desc, 0xaa, sizeof(surface_desc));
10736 surface_desc.dwSize = sizeof(surface_desc);
10737 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
10738 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
10739 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
10741 memset(&surface_desc, 0xaa, sizeof(surface_desc));
10742 surface_desc.dwSize = sizeof(surface_desc);
10743 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
10744 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
10745 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
10746 memset(&surface_desc, 0xaa, sizeof(surface_desc));
10747 surface_desc.dwSize = sizeof(surface_desc);
10748 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
10749 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
10750 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
10751 hr = IDirectDrawSurface4_Unlock(surface, NULL);
10752 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
10754 memset(&surface_desc, 0xaa, sizeof(surface_desc));
10755 surface_desc.dwSize = sizeof(surface_desc);
10756 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
10757 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
10758 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
10760 IDirectDrawSurface4_Release(surface);
10761 refcount = IDirectDraw4_Release(ddraw);
10762 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
10763 DestroyWindow(window);
10766 static void test_texturemapblend(void)
10768 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
10769 static RECT rect = {0, 0, 64, 128};
10770 IDirectDrawSurface4 *surface, *rt;
10771 IDirect3DViewport3 *viewport;
10772 DDSURFACEDESC2 surface_desc;
10773 IDirect3DTexture2 *texture;
10774 IDirect3DDevice3 *device;
10775 DWORD texturemapblend;
10776 IDirectDraw4 *ddraw;
10777 unsigned int color;
10778 IDirect3D3 *d3d;
10779 DDCOLORKEY ckey;
10780 ULONG refcount;
10781 DWORD value;
10782 HWND window;
10783 DDBLTFX fx;
10784 HRESULT hr;
10786 static struct
10788 struct vec4 position;
10789 D3DCOLOR diffuse;
10790 struct vec2 texcoord;
10792 test1_quads[] =
10794 {{ 0.0f, 0.0f, 0.0f, 1.0f}, 0xffffffff, {0.0f, 0.0f}},
10795 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0xffffffff, {0.0f, 1.0f}},
10796 {{640.0f, 0.0f, 0.0f, 1.0f}, 0xffffffff, {1.0f, 0.0f}},
10797 {{640.0f, 240.0f, 0.0f, 1.0f}, 0xffffffff, {1.0f, 1.0f}},
10798 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0x80ffffff, {0.0f, 0.0f}},
10799 {{ 0.0f, 480.0f, 0.0f, 1.0f}, 0x80ffffff, {0.0f, 1.0f}},
10800 {{640.0f, 240.0f, 0.0f, 1.0f}, 0x80ffffff, {1.0f, 0.0f}},
10801 {{640.0f, 480.0f, 0.0f, 1.0f}, 0x80ffffff, {1.0f, 1.0f}},
10803 test2_quads[] =
10805 {{ 0.0f, 0.0f, 0.0f, 1.0f}, 0x00ff0080, {0.0f, 0.0f}},
10806 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0x00ff0080, {0.0f, 1.0f}},
10807 {{640.0f, 0.0f, 0.0f, 1.0f}, 0x00ff0080, {1.0f, 0.0f}},
10808 {{640.0f, 240.0f, 0.0f, 1.0f}, 0x00ff0080, {1.0f, 1.0f}},
10809 {{ 0.0f, 240.0f, 0.0f, 1.0f}, 0x008000ff, {0.0f, 0.0f}},
10810 {{ 0.0f, 480.0f, 0.0f, 1.0f}, 0x008000ff, {0.0f, 1.0f}},
10811 {{640.0f, 240.0f, 0.0f, 1.0f}, 0x008000ff, {1.0f, 0.0f}},
10812 {{640.0f, 480.0f, 0.0f, 1.0f}, 0x008000ff, {1.0f, 1.0f}},
10815 window = create_window();
10816 if (!(device = create_device(window, DDSCL_NORMAL)))
10818 skip("Failed to create a 3D device, skipping test.\n");
10819 DestroyWindow(window);
10820 return;
10823 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
10824 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10825 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
10826 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10827 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
10828 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10830 viewport = create_viewport(device, 0, 0, 640, 480);
10831 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
10832 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10834 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, &texturemapblend);
10835 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10836 ok(texturemapblend == D3DTBLEND_MODULATE, "Got unexpected texture map blend %#lx.\n", texturemapblend);
10838 hr = IDirect3DDevice3_GetTextureStageState(device, 0, D3DTSS_ALPHAOP, &value);
10839 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10840 ok(value == D3DTOP_SELECTARG1, "Got unexpected D3DTSS_ALPHAOP value %#lx.\n", value);
10842 /* Test alpha with DDPF_ALPHAPIXELS texture - should be taken from texture
10843 * alpha channel.
10845 * The vertex alpha is completely ignored in this case, so case 1 and 2
10846 * combined are not a D3DTOP_MODULATE with texture alpha = 0xff in case 2
10847 * (no alpha in texture). */
10848 memset(&surface_desc, 0, sizeof(surface_desc));
10849 surface_desc.dwSize = sizeof(surface_desc);
10850 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
10851 surface_desc.dwHeight = 128;
10852 surface_desc.dwWidth = 128;
10853 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10854 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10855 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
10856 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10857 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10858 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10859 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10860 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
10861 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10862 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10864 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
10865 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10866 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
10867 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10869 hr = IDirect3DDevice3_GetTextureStageState(device, 0, D3DTSS_ALPHAOP, &value);
10870 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10871 ok(value == D3DTOP_SELECTARG1, "Got unexpected D3DTSS_ALPHAOP value %#lx.\n", value);
10873 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
10874 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10876 hr = IDirect3DDevice3_GetTextureStageState(device, 0, D3DTSS_ALPHAOP, &value);
10877 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10878 ok(value == D3DTOP_SELECTARG1, "Got unexpected D3DTSS_ALPHAOP value %#lx.\n", value);
10880 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
10881 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10883 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
10884 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10886 memset(&fx, 0, sizeof(fx));
10887 fx.dwSize = sizeof(fx);
10888 U5(fx).dwFillColor = 0xff0000ff;
10889 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10890 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10891 U5(fx).dwFillColor = 0x800000ff;
10892 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10893 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10895 /* Note that the ddraw1 version of this test runs tests 1-3 with
10896 * D3DRENDERSTATE_COLORKEYENABLE enabled, whereas this version only runs
10897 * test 4 with color keying on. Because no color key is set on the texture
10898 * this should not result in different behavior. */
10899 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
10900 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10901 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10902 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10903 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
10904 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10905 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
10906 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10907 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
10908 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10910 #if 0
10911 /* Disable the call to test that the device has this state by default. */
10912 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
10913 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10914 #endif
10916 /* Texture stage state does not change so legacy texture blending stays enabled. */
10917 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
10918 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10920 hr = IDirect3DDevice3_BeginScene(device);
10921 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10922 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10923 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
10924 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10925 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10926 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
10927 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10928 hr = IDirect3DDevice3_EndScene(device);
10929 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10931 color = get_surface_color(rt, 5, 5);
10932 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
10933 color = get_surface_color(rt, 400, 5);
10934 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10935 color = get_surface_color(rt, 5, 245);
10936 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
10937 color = get_surface_color(rt, 400, 245);
10938 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10940 /* Turn legacy texture blending off. */
10941 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
10942 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10943 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
10944 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10945 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
10946 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10947 hr = IDirect3DDevice3_BeginScene(device);
10948 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10949 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10950 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
10951 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10952 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10953 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
10954 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10955 hr = IDirect3DDevice3_EndScene(device);
10956 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10958 color = get_surface_color(rt, 5, 5);
10959 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10960 color = get_surface_color(rt, 400, 5);
10961 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10962 color = get_surface_color(rt, 5, 245);
10963 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
10964 color = get_surface_color(rt, 400, 245);
10965 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
10967 /* This doesn't turn legacy texture blending on again, as setting the same
10968 * _TEXTUREMAPBLEND value. */
10969 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
10970 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10971 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
10972 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10973 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
10974 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10975 hr = IDirect3DDevice3_BeginScene(device);
10976 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10977 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10978 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
10979 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10980 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10981 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
10982 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10983 hr = IDirect3DDevice3_EndScene(device);
10984 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10986 color = get_surface_color(rt, 5, 5);
10987 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10988 color = get_surface_color(rt, 400, 5);
10989 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10990 color = get_surface_color(rt, 5, 245);
10991 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
10992 color = get_surface_color(rt, 400, 245);
10993 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
10995 /* Turn legacy texture blending on again. */
10996 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_ADD);
10997 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10998 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
10999 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11000 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
11001 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11002 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11003 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11004 hr = IDirect3DDevice3_BeginScene(device);
11005 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11006 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
11007 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
11008 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11009 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
11010 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
11011 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11012 hr = IDirect3DDevice3_EndScene(device);
11013 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11015 color = get_surface_color(rt, 5, 5);
11016 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
11017 color = get_surface_color(rt, 400, 5);
11018 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
11019 color = get_surface_color(rt, 5, 245);
11020 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
11021 color = get_surface_color(rt, 400, 245);
11022 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
11024 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
11025 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11026 IDirect3DTexture2_Release(texture);
11027 refcount = IDirectDrawSurface4_Release(surface);
11028 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
11030 /* Test alpha with texture that has no alpha channel - alpha should be
11031 * taken from diffuse vertex color. */
11032 memset(&surface_desc, 0, sizeof(surface_desc));
11033 surface_desc.dwSize = sizeof(surface_desc);
11034 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
11035 surface_desc.dwHeight = 128;
11036 surface_desc.dwWidth = 128;
11037 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11038 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11039 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11040 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11041 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
11042 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
11043 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
11045 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11046 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11048 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
11049 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11050 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
11051 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11053 hr = IDirect3DDevice3_GetTextureStageState(device, 0, D3DTSS_ALPHAOP, &value);
11054 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11055 ok(value == D3DTOP_SELECTARG2, "Got unexpected D3DTSS_ALPHAOP value %#lx.\n", value);
11057 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11058 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11060 U5(fx).dwFillColor = 0xff0000ff;
11061 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11062 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11063 U5(fx).dwFillColor = 0x800000ff;
11064 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11065 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11067 hr = IDirect3DDevice3_BeginScene(device);
11068 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11069 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
11070 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
11071 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11072 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
11073 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
11074 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11075 hr = IDirect3DDevice3_EndScene(device);
11076 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
11078 color = get_surface_color(rt, 5, 5);
11079 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
11080 color = get_surface_color(rt, 400, 5);
11081 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
11082 color = get_surface_color(rt, 5, 245);
11083 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
11084 color = get_surface_color(rt, 400, 245);
11085 ok(compare_color(color, 0x00000080, 2), "Got unexpected color 0x%08x.\n", color);
11087 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
11088 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
11089 IDirect3DTexture2_Release(texture);
11090 refcount = IDirectDrawSurface4_Release(surface);
11091 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
11093 /* Test RGB - should multiply color components from diffuse vertex color
11094 * and texture. */
11095 memset(&surface_desc, 0, sizeof(surface_desc));
11096 surface_desc.dwSize = sizeof(surface_desc);
11097 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
11098 surface_desc.dwHeight = 128;
11099 surface_desc.dwWidth = 128;
11100 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11101 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11102 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
11103 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11104 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
11105 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
11106 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
11107 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
11108 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11109 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
11111 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
11112 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
11113 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
11114 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
11116 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11117 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
11119 U5(fx).dwFillColor = 0x00ffffff;
11120 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11121 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
11122 U5(fx).dwFillColor = 0x00ffff80;
11123 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11124 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
11126 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
11127 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
11129 hr = IDirect3DDevice3_BeginScene(device);
11130 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
11131 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
11132 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test2_quads[0], 4, 0);
11133 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
11134 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
11135 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test2_quads[4], 4, 0);
11136 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
11137 hr = IDirect3DDevice3_EndScene(device);
11138 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
11140 color = get_surface_color(rt, 5, 5);
11141 ok(compare_color(color, 0x00ff0040, 2), "Got unexpected color 0x%08x.\n", color);
11142 color = get_surface_color(rt, 400, 5);
11143 ok(compare_color(color, 0x00ff0080, 2), "Got unexpected color 0x%08x.\n", color);
11144 color = get_surface_color(rt, 5, 245);
11145 ok(compare_color(color, 0x00800080, 2), "Got unexpected color 0x%08x.\n", color);
11146 color = get_surface_color(rt, 400, 245);
11147 ok(compare_color(color, 0x008000ff, 2), "Got unexpected color 0x%08x.\n", color);
11149 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
11150 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
11151 IDirect3DTexture2_Release(texture);
11152 refcount = IDirectDrawSurface4_Release(surface);
11153 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
11155 /* Test alpha again, now with color keyed texture (colorkey emulation in
11156 * wine can interfere). */
11157 memset(&surface_desc, 0, sizeof(surface_desc));
11158 surface_desc.dwSize = sizeof(surface_desc);
11159 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
11160 surface_desc.dwHeight = 128;
11161 surface_desc.dwWidth = 128;
11162 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11163 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11164 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11165 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
11166 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
11167 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
11168 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
11170 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11171 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
11173 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
11174 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
11175 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
11176 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
11178 hr = IDirect3DViewport3_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
11179 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#lx.\n", hr);
11181 U5(fx).dwFillColor = 0xf800;
11182 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11183 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
11184 U5(fx).dwFillColor = 0x001f;
11185 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11186 ok(SUCCEEDED(hr), "Failed to clear texture, hr %#lx.\n", hr);
11188 ckey.dwColorSpaceLowValue = 0x001f;
11189 ckey.dwColorSpaceHighValue = 0x001f;
11190 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11191 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
11193 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
11194 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
11195 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
11196 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
11198 hr = IDirect3DDevice3_BeginScene(device);
11199 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
11200 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
11201 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[0], 4, 0);
11202 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
11203 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
11204 D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &test1_quads[4], 4, 0);
11205 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
11206 hr = IDirect3DDevice3_EndScene(device);
11207 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
11209 color = get_surface_color(rt, 5, 5);
11210 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
11211 color = get_surface_color(rt, 400, 5);
11212 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
11213 color = get_surface_color(rt, 5, 245);
11214 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
11215 color = get_surface_color(rt, 400, 245);
11216 ok(compare_color(color, 0x00800000, 2), "Got unexpected color 0x%08x.\n", color);
11218 hr = IDirect3DDevice3_SetTexture(device, 0, NULL);
11219 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
11220 IDirect3DTexture2_Release(texture);
11221 refcount = IDirectDrawSurface4_Release(surface);
11222 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
11224 destroy_viewport(device, viewport);
11225 IDirectDrawSurface4_Release(rt);
11226 IDirect3DDevice3_Release(device);
11227 IDirect3D3_Release(d3d);
11228 refcount = IDirectDraw4_Release(ddraw);
11229 ok(!refcount, "Ddraw object not properly released, refcount %lu.\n", refcount);
11230 DestroyWindow(window);
11233 static void test_signed_formats(void)
11235 unsigned int color, expected_color;
11236 HRESULT hr;
11237 IDirect3DDevice3 *device;
11238 IDirect3D3 *d3d;
11239 IDirectDraw4 *ddraw;
11240 IDirectDrawSurface4 *surface, *rt;
11241 IDirect3DTexture2 *texture;
11242 IDirect3DViewport3 *viewport;
11243 DDSURFACEDESC2 surface_desc;
11244 ULONG refcount;
11245 HWND window;
11246 D3DRECT clear_rect;
11247 static struct
11249 struct vec3 position;
11250 struct vec2 texcoord;
11252 quad[] =
11254 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
11255 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
11256 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
11257 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
11259 /* See test_signed_formats() in dlls/d3d9/tests/visual.c for an explanation
11260 * of these values. */
11261 static const USHORT content_v8u8[4][4] =
11263 {0x0000, 0x7f7f, 0x8880, 0x0000},
11264 {0x0080, 0x8000, 0x7f00, 0x007f},
11265 {0x193b, 0xe8c8, 0x0808, 0xf8f8},
11266 {0x4444, 0xc0c0, 0xa066, 0x22e0},
11268 static const DWORD content_x8l8v8u8[4][4] =
11270 {0x00000000, 0x00ff7f7f, 0x00008880, 0x00ff0000},
11271 {0x00000080, 0x00008000, 0x00007f00, 0x0000007f},
11272 {0x0041193b, 0x0051e8c8, 0x00040808, 0x00fff8f8},
11273 {0x00824444, 0x0000c0c0, 0x00c2a066, 0x009222e0},
11275 static const USHORT content_l6v5u5[4][4] =
11277 {0x0000, 0xfdef, 0x0230, 0xfc00},
11278 {0x0010, 0x0200, 0x01e0, 0x000f},
11279 {0x4067, 0x53b9, 0x0421, 0xffff},
11280 {0x8108, 0x0318, 0xc28c, 0x909c},
11282 static const struct
11284 const char *name;
11285 const void *content;
11286 SIZE_T pixel_size;
11287 BOOL blue;
11288 unsigned int slop, slop_broken;
11289 DDPIXELFORMAT format;
11291 formats[] =
11294 "D3DFMT_V8U8", content_v8u8, sizeof(WORD), FALSE, 1, 0,
11296 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV, 0,
11297 {16}, {0x000000ff}, {0x0000ff00}, {0x00000000}, {0x00000000}
11301 "D3DFMT_X8L8V8U8", content_x8l8v8u8, sizeof(DWORD), TRUE, 1, 0,
11303 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
11304 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
11308 "D3DFMT_L6V5U5", content_l6v5u5, sizeof(WORD), TRUE, 4, 7,
11310 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
11311 {16}, {0x0000001f}, {0x000003e0}, {0x0000fc00}, {0x00000000}
11315 /* No V16U16 or Q8W8V8U8 support in ddraw. */
11317 static const unsigned int expected_colors[4][4] =
11319 {0x00808080, 0x00fefeff, 0x00010780, 0x008080ff},
11320 {0x00018080, 0x00800180, 0x0080fe80, 0x00fe8080},
11321 {0x00ba98a0, 0x004767a8, 0x00888881, 0x007878ff},
11322 {0x00c3c3c0, 0x003f3f80, 0x00e51fe1, 0x005fa2c8},
11324 unsigned int i, width, x, y;
11325 D3DDEVICEDESC device_desc, hel_desc;
11327 window = create_window();
11328 if (!(device = create_device(window, DDSCL_NORMAL)))
11330 skip("Failed to create a 3D device, skipping test.\n");
11331 DestroyWindow(window);
11332 return;
11335 memset(&device_desc, 0, sizeof(device_desc));
11336 device_desc.dwSize = sizeof(device_desc);
11337 memset(&hel_desc, 0, sizeof(hel_desc));
11338 hel_desc.dwSize = sizeof(hel_desc);
11339 hr = IDirect3DDevice3_GetCaps(device, &device_desc, &hel_desc);
11340 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#lx.\n", hr);
11341 if (!(device_desc.dwTextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA))
11343 skip("D3DTOP_BLENDFACTORALPHA not supported, skipping bumpmap format tests.\n");
11344 goto done;
11347 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
11348 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
11349 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
11350 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#lx.\n", hr);
11351 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
11352 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
11354 memset(&surface_desc, 0, sizeof(surface_desc));
11355 surface_desc.dwSize = sizeof(surface_desc);
11356 hr = IDirectDrawSurface4_GetSurfaceDesc(rt, &surface_desc);
11357 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
11358 viewport = create_viewport(device, 0, 0, surface_desc.dwWidth, surface_desc.dwHeight);
11359 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
11360 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#lx.\n", hr);
11361 U1(clear_rect).x1 = 0;
11362 U2(clear_rect).y1 = 0;
11363 U3(clear_rect).x2 = surface_desc.dwWidth;
11364 U4(clear_rect).y2 = surface_desc.dwHeight;
11366 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
11367 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
11369 /* dst = tex * 0.5 + 1.0 * (1.0 - 0.5) = tex * 0.5 + 0.5 */
11370 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x80ffffff);
11371 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
11372 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
11373 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#lx.\n", hr);
11374 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
11375 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#lx.\n", hr);
11376 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
11377 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#lx.\n", hr);
11379 for (i = 0; i < ARRAY_SIZE(formats); i++)
11381 for (width = 1; width < 5; width += 3)
11383 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
11384 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
11386 memset(&surface_desc, 0, sizeof(surface_desc));
11387 surface_desc.dwSize = sizeof(surface_desc);
11388 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
11389 surface_desc.dwWidth = width;
11390 surface_desc.dwHeight = 4;
11391 U4(surface_desc).ddpfPixelFormat = formats[i].format;
11392 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
11393 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11394 if (FAILED(hr))
11396 skip("%s textures not supported, skipping.\n", formats[i].name);
11397 continue;
11399 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx, format %s.\n", hr, formats[i].name);
11401 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
11402 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture2 interface, hr %#lx, format %s.\n",
11403 hr, formats[i].name);
11404 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
11405 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx, format %s.\n", hr, formats[i].name);
11406 IDirect3DTexture2_Release(texture);
11408 memset(&surface_desc, 0, sizeof(surface_desc));
11409 surface_desc.dwSize = sizeof(surface_desc);
11410 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, 0, NULL);
11411 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx, format %s.\n", hr, formats[i].name);
11412 for (y = 0; y < 4; y++)
11414 memcpy((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch,
11415 (char *)formats[i].content + y * 4 * formats[i].pixel_size,
11416 width * formats[i].pixel_size);
11418 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11419 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, format %s.\n", hr, formats[i].name);
11421 hr = IDirect3DDevice3_BeginScene(device);
11422 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
11423 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
11424 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
11425 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
11426 hr = IDirect3DDevice3_EndScene(device);
11427 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
11429 for (y = 0; y < 4; y++)
11431 for (x = 0; x < width; x++)
11433 expected_color = expected_colors[y][x];
11434 if (!formats[i].blue)
11435 expected_color |= 0x000000ff;
11437 color = get_surface_color(rt, 80 + 160 * x, 60 + 120 * y);
11438 ok(compare_color(color, expected_color, formats[i].slop)
11439 || broken(compare_color(color, expected_color, formats[i].slop_broken)),
11440 "Expected color 0x%08x, got 0x%08x, format %s, location %ux%u.\n",
11441 expected_color, color, formats[i].name, x, y);
11445 IDirectDrawSurface4_Release(surface);
11449 destroy_viewport(device, viewport);
11450 IDirectDrawSurface4_Release(rt);
11451 IDirectDraw4_Release(ddraw);
11452 IDirect3D3_Release(d3d);
11454 done:
11455 refcount = IDirect3DDevice3_Release(device);
11456 ok(!refcount, "Device has %lu references left.\n", refcount);
11457 DestroyWindow(window);
11460 static void test_color_fill(void)
11462 HRESULT hr;
11463 IDirect3DDevice3 *device;
11464 IDirect3D3 *d3d;
11465 IDirectDraw4 *ddraw;
11466 IDirectDrawSurface4 *surface, *surface2;
11467 DDSURFACEDESC2 surface_desc;
11468 unsigned int i, *color;
11469 DDPIXELFORMAT z_fmt;
11470 ULONG refcount;
11471 HWND window;
11472 DDBLTFX fx;
11473 RECT rect = {5, 5, 7, 7};
11474 DWORD supported_fmts = 0, num_fourcc_codes, *fourcc_codes;
11475 DDCAPS hal_caps;
11476 static const struct
11478 DWORD caps, caps2;
11479 HRESULT colorfill_hr, depthfill_hr;
11480 BOOL rop_success;
11481 const char *name;
11482 unsigned int result;
11483 BOOL check_result;
11484 DDPIXELFORMAT format;
11486 tests[] =
11489 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
11490 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
11492 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11493 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
11497 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
11498 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
11500 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11501 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
11505 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
11506 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
11508 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11509 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
11513 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
11514 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
11516 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11517 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
11521 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
11522 DD_OK, DDERR_INVALIDPARAMS, TRUE, "managed texture RGB", 0xdeadbeef, TRUE,
11524 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11525 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
11529 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, 0,
11530 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0xdeadbeef, TRUE,
11531 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
11534 DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY, 0,
11535 DDERR_INVALIDPARAMS, DD_OK, TRUE, "sysmem zbuffer", 0xdeadbeef, TRUE,
11536 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
11539 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
11540 * different afterwards. DX9+ GPUs set one of the two luminance values
11541 * in each block, but AMD and Nvidia GPUs disagree on which luminance
11542 * value they set. r200 (dx8) just sets the entire block to the clear
11543 * value. */
11544 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
11545 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
11547 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
11548 {0}, {0}, {0}, {0}, {0}
11552 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
11553 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
11555 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
11556 {0}, {0}, {0}, {0}, {0}
11560 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
11561 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
11563 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
11564 {0}, {0}, {0}, {0}, {0}
11568 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
11569 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
11571 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
11572 {0}, {0}, {0}, {0}, {0}
11576 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
11577 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
11579 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
11580 {0}, {0}, {0}, {0}, {0}
11584 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
11585 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
11587 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
11588 {0}, {0}, {0}, {0}, {0}
11592 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
11593 * surface works, presumably because it is handled by the runtime instead of
11594 * the driver. */
11595 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
11596 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
11598 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
11599 {8}, {0}, {0}, {0}, {0}
11603 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
11604 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
11606 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
11607 {8}, {0}, {0}, {0}, {0}
11611 static const struct
11613 DWORD rop;
11614 const char *name;
11615 HRESULT hr;
11617 rops[] =
11619 {SRCCOPY, "SRCCOPY", DD_OK},
11620 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
11621 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
11622 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
11623 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
11624 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
11625 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
11626 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
11627 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
11628 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
11629 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
11630 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
11631 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
11632 {BLACKNESS, "BLACKNESS", DD_OK},
11633 {WHITENESS, "WHITENESS", DD_OK},
11634 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
11637 window = create_window();
11638 if (!(device = create_device(window, DDSCL_NORMAL)))
11640 skip("Failed to create a 3D device, skipping test.\n");
11641 DestroyWindow(window);
11642 return;
11645 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
11646 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
11647 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
11648 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#lx.\n", hr);
11650 memset(&z_fmt, 0, sizeof(z_fmt));
11651 IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
11652 if (!z_fmt.dwSize)
11653 skip("No Z buffer formats supported, skipping Z buffer colorfill test.\n");
11655 IDirect3DDevice3_EnumTextureFormats(device, test_block_formats_creation_cb, &supported_fmts);
11656 if (!(supported_fmts & SUPPORT_DXT1))
11657 skip("DXT1 textures not supported, skipping DXT1 colorfill test.\n");
11659 IDirect3D3_Release(d3d);
11661 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
11662 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
11663 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
11664 num_fourcc_codes * sizeof(*fourcc_codes));
11665 if (!fourcc_codes)
11666 goto done;
11667 hr = IDirectDraw4_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
11668 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
11669 for (i = 0; i < num_fourcc_codes; i++)
11671 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
11672 supported_fmts |= SUPPORT_YUY2;
11673 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
11674 supported_fmts |= SUPPORT_UYVY;
11676 HeapFree(GetProcessHeap(), 0, fourcc_codes);
11678 memset(&hal_caps, 0, sizeof(hal_caps));
11679 hal_caps.dwSize = sizeof(hal_caps);
11680 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
11681 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
11683 if (!(supported_fmts & (SUPPORT_YUY2 | SUPPORT_UYVY)) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
11684 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
11686 for (i = 0; i < ARRAY_SIZE(tests); i++)
11688 DWORD expected_broken = tests[i].result;
11690 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
11691 memset(&fx, 0, sizeof(fx));
11692 fx.dwSize = sizeof(fx);
11693 U5(fx).dwFillColor = 0xdeadbeef;
11695 memset(&surface_desc, 0, sizeof(surface_desc));
11696 surface_desc.dwSize = sizeof(surface_desc);
11697 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11698 surface_desc.dwWidth = 64;
11699 surface_desc.dwHeight = 64;
11700 U4(surface_desc).ddpfPixelFormat = tests[i].format;
11701 surface_desc.ddsCaps.dwCaps = tests[i].caps;
11702 surface_desc.ddsCaps.dwCaps2 = tests[i].caps2;
11704 if (tests[i].format.dwFourCC == MAKEFOURCC('D','X','T','1') && !(supported_fmts & SUPPORT_DXT1))
11705 continue;
11706 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !(supported_fmts & SUPPORT_YUY2))
11707 continue;
11708 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !(supported_fmts & SUPPORT_UYVY))
11709 continue;
11710 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
11711 continue;
11713 if (tests[i].caps & DDSCAPS_ZBUFFER)
11715 if (!z_fmt.dwSize)
11716 continue;
11718 U4(surface_desc).ddpfPixelFormat = z_fmt;
11719 /* Some drivers seem to convert depth values incorrectly or not at
11720 * all. Affects at least AMD PALM, 8.17.10.1247. */
11721 if (tests[i].caps & DDSCAPS_VIDEOMEMORY)
11723 DWORD expected;
11724 float f, g;
11726 expected = tests[i].result & U3(z_fmt).dwZBitMask;
11727 f = ceilf(logf(expected + 1.0f) / logf(2.0f));
11728 g = (f + 1.0f) / 2.0f;
11729 g -= (int)g;
11730 expected_broken = (expected / exp2f(f) - g) * 256;
11731 expected_broken *= 0x01010101;
11735 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11736 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx, surface %s.\n", hr, tests[i].name);
11738 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11739 todo_wine_if (tests[i].format.dwFourCC)
11740 ok(hr == tests[i].colorfill_hr, "Blt returned %#lx, expected %#lx, surface %s.\n",
11741 hr, tests[i].colorfill_hr, tests[i].name);
11743 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11744 todo_wine_if (tests[i].format.dwFourCC)
11745 ok(hr == tests[i].colorfill_hr, "Blt returned %#lx, expected %#lx, surface %s.\n",
11746 hr, tests[i].colorfill_hr, tests[i].name);
11748 if (SUCCEEDED(hr) && tests[i].check_result)
11750 memset(&surface_desc, 0, sizeof(surface_desc));
11751 surface_desc.dwSize = sizeof(surface_desc);
11752 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
11753 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
11754 color = surface_desc.lpSurface;
11755 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
11756 *color, tests[i].result, tests[i].name);
11757 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11758 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
11761 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11762 ok(hr == tests[i].depthfill_hr, "Blt returned %#lx, expected %#lx, surface %s.\n",
11763 hr, tests[i].depthfill_hr, tests[i].name);
11764 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11765 ok(hr == tests[i].depthfill_hr, "Blt returned %#lx, expected %#lx, surface %s.\n",
11766 hr, tests[i].depthfill_hr, tests[i].name);
11768 if (SUCCEEDED(hr) && tests[i].check_result)
11770 memset(&surface_desc, 0, sizeof(surface_desc));
11771 surface_desc.dwSize = sizeof(surface_desc);
11772 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
11773 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
11774 color = surface_desc.lpSurface;
11775 ok((*color & U3(z_fmt).dwZBitMask) == (tests[i].result & U3(z_fmt).dwZBitMask)
11776 || broken((*color & U3(z_fmt).dwZBitMask) == (expected_broken & U3(z_fmt).dwZBitMask)),
11777 "Got clear result 0x%08lx, expected 0x%08lx, surface %s.\n",
11778 *color & U3(z_fmt).dwZBitMask, tests[i].result & U3(z_fmt).dwZBitMask, tests[i].name);
11779 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11780 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
11783 U5(fx).dwFillColor = 0xdeadbeef;
11784 fx.dwROP = BLACKNESS;
11785 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
11786 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#lx, expected %s, surface %s.\n",
11787 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
11788 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08lx, surface %s\n",
11789 U5(fx).dwFillColor, tests[i].name);
11791 if (SUCCEEDED(hr) && tests[i].check_result)
11793 memset(&surface_desc, 0, sizeof(surface_desc));
11794 surface_desc.dwSize = sizeof(surface_desc);
11795 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
11796 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
11797 color = surface_desc.lpSurface;
11798 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
11799 *color, tests[i].name);
11800 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11801 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
11804 fx.dwROP = WHITENESS;
11805 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
11806 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#lx, expected %s, surface %s.\n",
11807 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
11808 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08lx, surface %s\n",
11809 U5(fx).dwFillColor, tests[i].name);
11811 if (SUCCEEDED(hr) && tests[i].check_result)
11813 memset(&surface_desc, 0, sizeof(surface_desc));
11814 surface_desc.dwSize = sizeof(surface_desc);
11815 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
11816 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
11817 color = surface_desc.lpSurface;
11818 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
11819 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
11820 *color, tests[i].name);
11821 hr = IDirectDrawSurface4_Unlock(surface, NULL);
11822 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, surface %s.\n", hr, tests[i].name);
11825 IDirectDrawSurface4_Release(surface);
11828 memset(&fx, 0, sizeof(fx));
11829 fx.dwSize = sizeof(fx);
11830 U5(fx).dwFillColor = 0xdeadbeef;
11831 fx.dwROP = WHITENESS;
11833 memset(&surface_desc, 0, sizeof(surface_desc));
11834 surface_desc.dwSize = sizeof(surface_desc);
11835 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11836 surface_desc.dwWidth = 64;
11837 surface_desc.dwHeight = 64;
11838 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11839 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11840 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11841 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
11842 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
11843 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
11844 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
11845 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11846 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
11847 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
11848 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
11850 /* No DDBLTFX. */
11851 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
11852 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11853 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
11854 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11856 /* Unused source rectangle. */
11857 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11858 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
11859 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
11860 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
11862 /* Unused source surface. */
11863 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11864 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11865 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
11866 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
11867 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11868 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11869 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
11870 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
11872 /* Inverted destination or source rectangle. */
11873 SetRect(&rect, 5, 7, 7, 5);
11874 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11875 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
11876 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11877 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
11878 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11879 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11880 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11881 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11882 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
11883 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
11885 /* Negative rectangle. */
11886 SetRect(&rect, -1, -1, 5, 5);
11887 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11888 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
11889 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11890 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
11891 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11892 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11893 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11894 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11895 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
11896 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
11898 /* Out of bounds rectangle. */
11899 SetRect(&rect, 0, 0, 65, 65);
11900 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11901 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
11902 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
11903 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
11905 /* Combine multiple flags. */
11906 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11907 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
11908 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
11909 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11910 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
11911 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11913 for (i = 0; i < ARRAY_SIZE(rops); i++)
11915 fx.dwROP = rops[i].rop;
11916 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
11917 ok(hr == rops[i].hr, "Got unexpected hr %#lx for rop %s.\n", hr, rops[i].name);
11920 IDirectDrawSurface4_Release(surface2);
11921 IDirectDrawSurface4_Release(surface);
11923 if (!z_fmt.dwSize)
11924 goto done;
11926 memset(&surface_desc, 0, sizeof(surface_desc));
11927 surface_desc.dwSize = sizeof(surface_desc);
11928 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11929 surface_desc.dwWidth = 64;
11930 surface_desc.dwHeight = 64;
11931 U4(surface_desc).ddpfPixelFormat = z_fmt;
11932 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
11933 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11934 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
11935 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
11936 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
11938 /* No DDBLTFX. */
11939 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
11940 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11942 /* Unused source rectangle. */
11943 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11944 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
11946 /* Unused source surface. */
11947 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11948 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11949 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11950 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11952 /* Inverted destination or source rectangle. */
11953 SetRect(&rect, 5, 7, 7, 5);
11954 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11955 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
11956 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11957 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
11958 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11959 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11960 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11961 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11963 /* Negative rectangle. */
11964 SetRect(&rect, -1, -1, 5, 5);
11965 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11966 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
11967 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11968 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
11969 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11970 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11971 hr = IDirectDrawSurface4_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11972 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11974 /* Out of bounds rectangle. */
11975 SetRect(&rect, 0, 0, 65, 65);
11976 hr = IDirectDrawSurface4_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11977 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#lx.\n", hr);
11979 /* Combine multiple flags. */
11980 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11981 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
11983 IDirectDrawSurface4_Release(surface2);
11984 IDirectDrawSurface4_Release(surface);
11986 done:
11987 IDirectDraw4_Release(ddraw);
11988 refcount = IDirect3DDevice3_Release(device);
11989 ok(!refcount, "Device has %lu references left.\n", refcount);
11990 DestroyWindow(window);
11993 static void test_texcoordindex(void)
11995 static struct
11997 struct vec3 pos;
11998 struct vec2 texcoord1;
11999 struct vec2 texcoord2;
12000 struct vec2 texcoord3;
12002 quad[] =
12004 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}},
12005 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}},
12006 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}},
12007 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}},
12009 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_TEX3;
12010 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
12011 IDirect3DDevice3 *device;
12012 unsigned int color;
12013 IDirect3D3 *d3d;
12014 IDirectDraw4 *ddraw;
12015 IDirectDrawSurface4 *rt;
12016 IDirect3DViewport3 *viewport;
12017 HWND window;
12018 HRESULT hr;
12019 IDirectDrawSurface4 *surface1, *surface2;
12020 IDirect3DTexture2 *texture1, *texture2;
12021 DDSURFACEDESC2 surface_desc;
12022 ULONG refcount;
12023 DWORD *ptr;
12025 window = create_window();
12026 if (!(device = create_device(window, DDSCL_NORMAL)))
12028 skip("Failed to create a 3D device, skipping test.\n");
12029 DestroyWindow(window);
12030 return;
12033 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
12034 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#lx.\n", hr);
12035 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
12036 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#lx.\n", hr);
12037 IDirect3D3_Release(d3d);
12039 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
12040 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
12042 memset(&surface_desc, 0, sizeof(surface_desc));
12043 surface_desc.dwSize = sizeof(surface_desc);
12044 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12045 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
12046 surface_desc.dwWidth = 2;
12047 surface_desc.dwHeight = 2;
12048 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
12049 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12050 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
12051 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
12052 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
12053 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
12054 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
12055 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
12056 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
12057 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
12058 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
12060 memset(&surface_desc, 0, sizeof(surface_desc));
12061 surface_desc.dwSize = sizeof(surface_desc);
12062 hr = IDirectDrawSurface4_Lock(surface1, 0, &surface_desc, 0, NULL);
12063 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12064 ptr = surface_desc.lpSurface;
12065 ptr[0] = 0xff000000;
12066 ptr[1] = 0xff00ff00;
12067 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
12068 ptr[0] = 0xff0000ff;
12069 ptr[1] = 0xff00ffff;
12070 hr = IDirectDrawSurface4_Unlock(surface1, NULL);
12071 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12073 memset(&surface_desc, 0, sizeof(surface_desc));
12074 surface_desc.dwSize = sizeof(surface_desc);
12075 hr = IDirectDrawSurface4_Lock(surface2, 0, &surface_desc, 0, NULL);
12076 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12077 ptr = surface_desc.lpSurface;
12078 ptr[0] = 0xff000000;
12079 ptr[1] = 0xff0000ff;
12080 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
12081 ptr[0] = 0xffff0000;
12082 ptr[1] = 0xffff00ff;
12083 hr = IDirectDrawSurface4_Unlock(surface2, 0);
12084 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12086 viewport = create_viewport(device, 0, 0, 640, 480);
12087 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
12088 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
12090 hr = IDirectDrawSurface4_QueryInterface(surface1, &IID_IDirect3DTexture2, (void **)&texture1);
12091 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
12092 hr = IDirectDrawSurface4_QueryInterface(surface2, &IID_IDirect3DTexture2, (void **)&texture2);
12093 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
12094 hr = IDirect3DDevice3_SetTexture(device, 0, texture1);
12095 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
12096 hr = IDirect3DDevice3_SetTexture(device, 1, texture2);
12097 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
12098 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
12099 ok(SUCCEEDED(hr), "Failed to set color op, hr %#lx.\n", hr);
12100 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
12101 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#lx.\n", hr);
12102 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
12103 ok(SUCCEEDED(hr), "Failed to set color op, hr %#lx.\n", hr);
12104 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
12105 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#lx.\n", hr);
12106 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
12107 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#lx.\n", hr);
12108 hr = IDirect3DDevice3_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
12109 ok(SUCCEEDED(hr), "Failed to set color op, hr %#lx.\n", hr);
12111 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_TEXCOORDINDEX, 1);
12112 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#lx.\n", hr);
12113 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 0);
12114 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#lx.\n", hr);
12116 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
12117 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#lx.\n", hr);
12119 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
12120 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
12122 hr = IDirect3DDevice3_BeginScene(device);
12123 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
12124 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
12125 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12126 hr = IDirect3DDevice3_EndScene(device);
12127 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
12129 color = get_surface_color(rt, 160, 120);
12130 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
12131 color = get_surface_color(rt, 480, 120);
12132 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
12133 color = get_surface_color(rt, 160, 360);
12134 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
12135 color = get_surface_color(rt, 480, 360);
12136 ok(compare_color(color, 0x00ffffff, 2), "Got unexpected color 0x%08x.\n", color);
12138 /* D3DTSS_TEXTURETRANSFORMFLAGS was introduced in D3D7, can't test it here. */
12140 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 2);
12141 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#lx.\n", hr);
12143 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
12144 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
12146 hr = IDirect3DDevice3_BeginScene(device);
12147 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
12148 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
12149 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12150 hr = IDirect3DDevice3_EndScene(device);
12151 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
12153 color = get_surface_color(rt, 160, 120);
12154 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
12155 color = get_surface_color(rt, 480, 120);
12156 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
12157 color = get_surface_color(rt, 160, 360);
12158 ok(compare_color(color, 0x00ff00ff, 2), "Got unexpected color 0x%08x.\n", color);
12159 color = get_surface_color(rt, 480, 360);
12160 ok(compare_color(color, 0x00ffff00, 2), "Got unexpected color 0x%08x.\n", color);
12162 IDirect3DTexture2_Release(texture2);
12163 IDirect3DTexture2_Release(texture1);
12164 IDirectDrawSurface4_Release(surface2);
12165 IDirectDrawSurface4_Release(surface1);
12167 destroy_viewport(device, viewport);
12169 IDirectDrawSurface4_Release(rt);
12170 IDirectDraw4_Release(ddraw);
12171 refcount = IDirect3DDevice3_Release(device);
12172 ok(!refcount, "Device has %lu references left.\n", refcount);
12173 DestroyWindow(window);
12176 static void test_colorkey_precision(void)
12178 static struct
12180 struct vec3 pos;
12181 struct vec2 texcoord;
12183 quad[] =
12185 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
12186 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
12187 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
12188 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
12190 unsigned int data[4] = {0}, color_mask, color, t, c;
12191 IDirect3DDevice3 *device;
12192 IDirect3D3 *d3d;
12193 IDirectDraw4 *ddraw;
12194 IDirectDrawSurface4 *rt;
12195 IDirect3DViewport3 *viewport;
12196 HWND window;
12197 HRESULT hr;
12198 IDirectDrawSurface4 *src, *dst, *texture;
12199 IDirect3DTexture2 *d3d_texture;
12200 DDSURFACEDESC2 surface_desc, lock_desc;
12201 ULONG refcount;
12202 DDCOLORKEY ckey;
12203 DDBLTFX fx;
12204 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
12205 BOOL is_nvidia, is_warp;
12206 static const struct
12208 unsigned int max, shift, bpp, clear;
12209 const char *name;
12210 BOOL skip_nv;
12211 DDPIXELFORMAT fmt;
12213 tests[] =
12216 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
12218 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
12219 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
12224 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
12226 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
12227 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
12232 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
12234 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
12235 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
12240 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
12242 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
12243 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
12248 window = create_window();
12249 if (!(device = create_device(window, DDSCL_NORMAL)))
12251 skip("Failed to create a 3D device, skipping test.\n");
12252 DestroyWindow(window);
12253 return;
12256 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
12257 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#lx.\n", hr);
12258 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
12259 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#lx.\n", hr);
12260 IDirect3D3_Release(d3d);
12261 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
12262 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
12264 is_nvidia = ddraw_is_nvidia(ddraw);
12265 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
12266 * (color key doesn't match although the values are equal), and a false
12267 * positive when the color key is 0 and the texture contains the value 1.
12268 * I don't want to mark this broken unconditionally since this would
12269 * essentially disable the test on Windows. Also on random occasions
12270 * 254 == 255 and 255 != 255.*/
12271 is_warp = ddraw_is_warp(ddraw);
12273 viewport = create_viewport(device, 0, 0, 640, 480);
12274 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
12275 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
12277 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
12278 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#lx.\n", hr);
12279 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
12280 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#lx.\n", hr);
12281 /* Multiply the texture read result with 0, that way the result color if the key doesn't
12282 * match is constant. In theory color keying works without reading the texture result
12283 * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
12284 * to differ. */
12285 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
12286 ok(SUCCEEDED(hr), "Failed to set color op, hr %#lx.\n", hr);
12287 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
12288 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#lx.\n", hr);
12289 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
12290 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#lx.\n", hr);
12291 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
12292 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
12294 memset(&fx, 0, sizeof(fx));
12295 fx.dwSize = sizeof(fx);
12296 memset(&lock_desc, 0, sizeof(lock_desc));
12297 lock_desc.dwSize = sizeof(lock_desc);
12299 for (t = 0; t < ARRAY_SIZE(tests); ++t)
12301 if (is_nvidia && tests[t].skip_nv)
12303 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
12304 continue;
12307 memset(&surface_desc, 0, sizeof(surface_desc));
12308 surface_desc.dwSize = sizeof(surface_desc);
12309 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12310 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12311 surface_desc.dwWidth = 4;
12312 surface_desc.dwHeight = 1;
12313 U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
12314 /* Windows XP (at least with the r200 driver, other drivers untested) produces
12315 * garbage when doing color keyed texture->texture blits. */
12316 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
12317 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
12318 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
12319 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
12321 U5(fx).dwFillColor = tests[t].clear;
12322 /* On the w8 testbot (WARP driver) the blit result has different values in the
12323 * X channel. */
12324 color_mask = U2(tests[t].fmt).dwRBitMask
12325 | U3(tests[t].fmt).dwGBitMask
12326 | U4(tests[t].fmt).dwBBitMask;
12328 for (c = 0; c <= tests[t].max; ++c)
12330 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
12331 * texture after it has been set once... */
12332 surface_desc.dwFlags |= DDSD_CKSRCBLT;
12333 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
12334 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
12335 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
12336 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &texture, NULL);
12337 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
12338 hr = IDirectDrawSurface4_QueryInterface(texture, &IID_IDirect3DTexture2, (void **)&d3d_texture);
12339 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
12340 hr = IDirect3DDevice3_SetTexture(device, 0, d3d_texture);
12341 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
12343 hr = IDirectDrawSurface4_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12344 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#lx.\n", hr);
12346 hr = IDirectDrawSurface4_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
12347 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12348 switch (tests[t].bpp)
12350 case 4:
12351 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
12352 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
12353 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
12354 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
12355 break;
12357 case 2:
12358 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
12359 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
12360 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
12361 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
12362 break;
12364 hr = IDirectDrawSurface4_Unlock(src, 0);
12365 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12366 hr = IDirectDrawSurface4_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
12367 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
12369 ckey.dwColorSpaceLowValue = c << tests[t].shift;
12370 ckey.dwColorSpaceHighValue = c << tests[t].shift;
12371 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12372 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
12374 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
12375 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
12377 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
12378 hr = IDirectDrawSurface4_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
12379 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12380 switch (tests[t].bpp)
12382 case 4:
12383 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
12384 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
12385 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
12386 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
12387 break;
12389 case 2:
12390 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
12391 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
12392 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
12393 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
12394 break;
12396 hr = IDirectDrawSurface4_Unlock(dst, 0);
12397 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12399 if (!c)
12401 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
12402 tests[t].clear, data[0], tests[t].name, c);
12404 if (data[3] == tests[t].clear)
12406 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
12407 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
12408 * even when a different surface is used. The blit itself doesn't draw anything,
12409 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
12410 * never be masked out by the key.
12412 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
12413 * test is disabled entirely.
12415 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
12416 * terrible on WARP. */
12417 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
12418 IDirect3DTexture2_Release(d3d_texture);
12419 IDirectDrawSurface4_Release(texture);
12420 IDirectDrawSurface4_Release(src);
12421 IDirectDrawSurface4_Release(dst);
12422 goto done;
12425 else
12426 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
12427 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
12429 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
12430 tests[t].clear, data[1], tests[t].name, c);
12432 if (c == tests[t].max)
12433 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
12434 tests[t].clear, data[2], tests[t].name, c);
12435 else
12436 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
12437 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
12439 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
12440 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
12442 hr = IDirect3DDevice3_BeginScene(device);
12443 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
12444 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
12445 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12446 hr = IDirect3DDevice3_EndScene(device);
12447 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
12449 color = get_surface_color(rt, 80, 240);
12450 if (!c)
12451 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
12452 "Got unexpected color 0x%08x, format %s, c=%u.\n",
12453 color, tests[t].name, c);
12454 else
12455 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
12456 "Got unexpected color 0x%08x, format %s, c=%u.\n",
12457 color, tests[t].name, c);
12459 color = get_surface_color(rt, 240, 240);
12460 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
12461 "Got unexpected color 0x%08x, format %s, c=%u.\n",
12462 color, tests[t].name, c);
12464 color = get_surface_color(rt, 400, 240);
12465 if (c == tests[t].max)
12466 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
12467 "Got unexpected color 0x%08x, format %s, c=%u.\n",
12468 color, tests[t].name, c);
12469 else
12470 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
12471 "Got unexpected color 0x%08x, format %s, c=%u.\n",
12472 color, tests[t].name, c);
12474 IDirect3DTexture2_Release(d3d_texture);
12475 IDirectDrawSurface4_Release(texture);
12477 IDirectDrawSurface4_Release(src);
12478 IDirectDrawSurface4_Release(dst);
12480 done:
12482 destroy_viewport(device, viewport);
12483 IDirectDrawSurface4_Release(rt);
12484 IDirectDraw4_Release(ddraw);
12485 refcount = IDirect3DDevice3_Release(device);
12486 ok(!refcount, "Device has %lu references left.\n", refcount);
12487 DestroyWindow(window);
12490 static void test_range_colorkey(void)
12492 IDirectDraw4 *ddraw;
12493 HWND window;
12494 HRESULT hr;
12495 IDirectDrawSurface4 *surface;
12496 DDSURFACEDESC2 surface_desc;
12497 ULONG refcount;
12498 DDCOLORKEY ckey;
12500 window = create_window();
12501 ddraw = create_ddraw();
12502 ok(!!ddraw, "Failed to create a ddraw object.\n");
12503 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12504 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
12506 memset(&surface_desc, 0, sizeof(surface_desc));
12507 surface_desc.dwSize = sizeof(surface_desc);
12508 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
12509 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
12510 surface_desc.dwWidth = 1;
12511 surface_desc.dwHeight = 1;
12512 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
12513 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
12514 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
12515 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
12516 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
12517 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
12519 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
12520 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
12521 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
12522 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12523 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
12525 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
12526 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
12527 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12528 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
12530 /* Same for DDSCAPS_OFFSCREENPLAIN. */
12531 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12532 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
12533 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
12534 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12535 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
12537 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
12538 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
12539 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12540 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
12542 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
12543 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
12544 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12545 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
12547 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
12548 ckey.dwColorSpaceLowValue = 0x00000000;
12549 ckey.dwColorSpaceHighValue = 0x00000001;
12550 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
12551 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
12553 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
12554 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
12555 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
12556 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
12558 ckey.dwColorSpaceLowValue = 0x00000001;
12559 ckey.dwColorSpaceHighValue = 0x00000000;
12560 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
12561 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
12563 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
12564 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
12565 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
12566 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
12568 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
12569 ckey.dwColorSpaceLowValue = 0x00000000;
12570 ckey.dwColorSpaceHighValue = 0x00000000;
12571 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
12572 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
12574 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
12575 ckey.dwColorSpaceLowValue = 0x00000001;
12576 ckey.dwColorSpaceHighValue = 0x00000000;
12577 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
12578 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
12579 ckey.dwColorSpaceLowValue = 0x00000000;
12580 ckey.dwColorSpaceHighValue = 0x00000001;
12581 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
12582 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
12583 /* Range destination keys don't work either. */
12584 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
12585 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
12587 /* Just to show it's not because of A, R, and G having equal values. */
12588 ckey.dwColorSpaceLowValue = 0x00000000;
12589 ckey.dwColorSpaceHighValue = 0x01010101;
12590 hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
12591 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#lx.\n", hr);
12593 /* None of these operations modified the key. */
12594 hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
12595 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
12596 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceLowValue);
12597 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08lx.\n", ckey.dwColorSpaceHighValue);
12599 IDirectDrawSurface4_Release(surface);
12600 refcount = IDirectDraw4_Release(ddraw);
12601 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
12602 DestroyWindow(window);
12605 static void test_shademode(void)
12607 IDirect3DVertexBuffer *vb_strip, *vb_list, *buffer;
12608 unsigned int color0, color1, count, i;
12609 IDirect3DViewport3 *viewport;
12610 IDirect3DDevice3 *device;
12611 D3DVERTEXBUFFERDESC desc;
12612 IDirectDrawSurface4 *rt;
12613 void *data = NULL;
12614 IDirect3D3 *d3d;
12615 ULONG refcount;
12616 HWND window;
12617 HRESULT hr;
12618 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
12619 static const struct
12621 struct vec3 position;
12622 DWORD diffuse;
12624 quad_strip[] =
12626 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
12627 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
12628 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
12629 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
12631 quad_list[] =
12633 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
12634 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
12635 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
12637 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
12638 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
12639 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
12641 static const struct
12643 DWORD primtype;
12644 DWORD shademode;
12645 unsigned int color0, color1;
12647 tests[] =
12649 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
12650 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
12651 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
12652 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
12653 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
12654 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
12657 window = create_window();
12658 if (!(device = create_device(window, DDSCL_NORMAL)))
12660 skip("Failed to create a 3D device, skipping test.\n");
12661 DestroyWindow(window);
12662 return;
12665 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
12666 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#lx.\n", hr);
12667 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
12668 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
12670 viewport = create_viewport(device, 0, 0, 640, 480);
12671 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
12672 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#lx.\n", hr);
12674 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
12675 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#lx.\n", hr);
12677 memset(&desc, 0, sizeof(desc));
12678 desc.dwSize = sizeof(desc);
12679 desc.dwCaps = D3DVBCAPS_WRITEONLY;
12680 desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
12681 desc.dwNumVertices = ARRAY_SIZE(quad_strip);
12682 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &vb_strip, 0, NULL);
12683 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#lx.\n", hr);
12684 hr = IDirect3DVertexBuffer_Lock(vb_strip, 0, &data, NULL);
12685 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#lx.\n", hr);
12686 memcpy(data, quad_strip, sizeof(quad_strip));
12687 hr = IDirect3DVertexBuffer_Unlock(vb_strip);
12688 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#lx.\n", hr);
12690 desc.dwNumVertices = ARRAY_SIZE(quad_list);
12691 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &vb_list, 0, NULL);
12692 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#lx.\n", hr);
12693 hr = IDirect3DVertexBuffer_Lock(vb_list, 0, &data, NULL);
12694 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#lx.\n", hr);
12695 memcpy(data, quad_list, sizeof(quad_list));
12696 hr = IDirect3DVertexBuffer_Unlock(vb_list);
12697 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#lx.\n", hr);
12699 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
12700 * the color fixups we have to do for FLAT shading will be dependent on that. */
12702 for (i = 0; i < ARRAY_SIZE(tests); ++i)
12704 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
12705 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
12707 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
12708 ok(hr == D3D_OK, "Failed to set shade mode, hr %#lx.\n", hr);
12710 hr = IDirect3DDevice3_BeginScene(device);
12711 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
12712 buffer = tests[i].primtype == D3DPT_TRIANGLESTRIP ? vb_strip : vb_list;
12713 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
12714 hr = IDirect3DDevice3_DrawPrimitiveVB(device, tests[i].primtype, buffer, 0, count, 0);
12715 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
12716 hr = IDirect3DDevice3_EndScene(device);
12717 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
12719 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
12720 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
12722 /* For D3DSHADE_FLAT it should take the color of the first vertex of
12723 * each triangle. This requires EXT_provoking_vertex or similar
12724 * functionality being available. */
12725 /* PHONG should be the same as GOURAUD, since no hardware implements
12726 * this. */
12727 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
12728 i, color0, tests[i].color0);
12729 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
12730 i, color1, tests[i].color1);
12733 IDirect3DVertexBuffer_Release(vb_strip);
12734 IDirect3DVertexBuffer_Release(vb_list);
12735 destroy_viewport(device, viewport);
12736 IDirectDrawSurface4_Release(rt);
12737 IDirect3D3_Release(d3d);
12738 refcount = IDirect3DDevice3_Release(device);
12739 ok(!refcount, "Device has %lu references left.\n", refcount);
12740 DestroyWindow(window);
12743 static void test_lockrect_invalid(void)
12745 unsigned int i, r;
12746 IDirectDraw4 *ddraw;
12747 IDirectDrawSurface4 *surface;
12748 HWND window;
12749 HRESULT hr;
12750 DDSURFACEDESC2 surface_desc;
12751 DDCAPS hal_caps;
12752 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
12753 static RECT valid[] =
12755 {60, 60, 68, 68},
12756 {60, 60, 60, 68},
12757 {60, 60, 68, 60},
12758 {120, 60, 128, 68},
12759 {60, 120, 68, 128},
12761 static RECT invalid[] =
12763 {68, 60, 60, 68}, /* left > right */
12764 {60, 68, 68, 60}, /* top > bottom */
12765 {-8, 60, 0, 68}, /* left < surface */
12766 {60, -8, 68, 0}, /* top < surface */
12767 {-16, 60, -8, 68}, /* right < surface */
12768 {60, -16, 68, -8}, /* bottom < surface */
12769 {60, 60, 136, 68}, /* right > surface */
12770 {60, 60, 68, 136}, /* bottom > surface */
12771 {136, 60, 144, 68}, /* left > surface */
12772 {60, 136, 68, 144}, /* top > surface */
12774 static const struct
12776 DWORD caps, caps2;
12777 const char *name;
12778 BOOL allowed;
12779 HRESULT hr;
12781 resources[] =
12783 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", TRUE, DDERR_INVALIDPARAMS},
12784 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", TRUE, DDERR_INVALIDPARAMS},
12785 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", TRUE, DDERR_INVALIDPARAMS},
12786 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", TRUE, DDERR_INVALIDPARAMS},
12787 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", TRUE, DDERR_INVALIDPARAMS},
12789 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_WRITEONLY, 0, "sysmem offscreenplain writeonly", FALSE, DDERR_INVALIDPARAMS},
12790 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_WRITEONLY, 0, "vidmem offscreenplain writeonly", FALSE, DDERR_INVALIDPARAMS},
12791 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_WRITEONLY, 0, "sysmem texture writeonly", FALSE, DDERR_INVALIDPARAMS},
12792 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_WRITEONLY, 0, "vidmem texture writeonly", FALSE, DDERR_INVALIDPARAMS},
12793 {DDSCAPS_TEXTURE | DDSCAPS_WRITEONLY, DDSCAPS2_TEXTUREMANAGE, "managed texture writeonly", TRUE, DDERR_INVALIDPARAMS},
12796 window = create_window();
12797 ddraw = create_ddraw();
12798 ok(!!ddraw, "Failed to create a ddraw object.\n");
12799 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12800 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
12802 memset(&hal_caps, 0, sizeof(hal_caps));
12803 hal_caps.dwSize = sizeof(hal_caps);
12804 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
12805 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
12806 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
12807 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
12809 skip("Required surface types not supported, skipping test.\n");
12810 goto done;
12813 for (r = 0; r < ARRAY_SIZE(resources); ++r)
12815 memset(&surface_desc, 0, sizeof(surface_desc));
12816 surface_desc.dwSize = sizeof(surface_desc);
12817 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12818 surface_desc.ddsCaps.dwCaps = resources[r].caps;
12819 surface_desc.ddsCaps.dwCaps2 = resources[r].caps2;
12820 surface_desc.dwWidth = 128;
12821 surface_desc.dwHeight = 128;
12822 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
12823 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
12824 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
12825 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xff0000;
12826 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x00ff00;
12827 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000ff;
12829 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12830 if (!resources[r].allowed)
12832 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#lx, type %s.\n", hr, resources[r].name);
12833 continue;
12835 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx, type %s.\n", hr, resources[r].name);
12837 hr = IDirectDrawSurface4_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
12838 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx, type %s.\n", hr, resources[r].name);
12840 for (i = 0; i < ARRAY_SIZE(valid); ++i)
12842 RECT *rect = &valid[i];
12844 memset(&surface_desc, 0, sizeof(surface_desc));
12845 surface_desc.dwSize = sizeof(surface_desc);
12847 hr = IDirectDrawSurface4_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
12848 ok(SUCCEEDED(hr), "Lock failed (%#lx) for rect %s, type %s.\n",
12849 hr, wine_dbgstr_rect(rect), resources[r].name);
12851 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12852 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
12855 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
12857 RECT *rect = &invalid[i];
12859 memset(&surface_desc, 1, sizeof(surface_desc));
12860 surface_desc.dwSize = sizeof(surface_desc);
12862 hr = IDirectDrawSurface4_Lock(surface, rect, &surface_desc, DDLOCK_WAIT, NULL);
12863 ok(hr == resources[r].hr, "Lock returned %#lx for rect %s, type %s.\n",
12864 hr, wine_dbgstr_rect(rect), resources[r].name);
12865 if (SUCCEEDED(hr))
12867 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12868 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
12870 else
12871 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
12874 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12875 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#lx, type %s.\n",
12876 hr, resources[r].name);
12877 hr = IDirectDrawSurface4_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12878 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#lx, type %s.\n",
12879 hr, resources[r].name);
12880 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12881 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
12883 hr = IDirectDrawSurface4_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
12884 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#lx).\n", wine_dbgstr_rect(&valid[0]), hr);
12885 hr = IDirectDrawSurface4_Lock(surface, &valid[0], &surface_desc, DDLOCK_WAIT, NULL);
12886 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#lx).\n",
12887 wine_dbgstr_rect(&valid[0]), hr);
12889 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
12890 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
12892 hr = IDirectDrawSurface4_Unlock(surface, NULL);
12893 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
12895 IDirectDrawSurface4_Release(surface);
12898 done:
12899 IDirectDraw4_Release(ddraw);
12900 DestroyWindow(window);
12903 static void test_yv12_overlay(void)
12905 IDirectDrawSurface4 *src_surface, *dst_surface;
12906 RECT rect = {13, 17, 14, 18};
12907 unsigned int offset, y;
12908 DDSURFACEDESC2 desc;
12909 unsigned char *base;
12910 IDirectDraw4 *ddraw;
12911 HWND window;
12912 HRESULT hr;
12914 window = create_window();
12915 ddraw = create_ddraw();
12916 ok(!!ddraw, "Failed to create a ddraw object.\n");
12917 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12918 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
12920 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
12922 skip("Failed to create a YV12 overlay, skipping test.\n");
12923 goto done;
12926 memset(&desc, 0, sizeof(desc));
12927 desc.dwSize = sizeof(desc);
12928 hr = IDirectDrawSurface4_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
12929 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12931 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
12932 "Got unexpected flags %#lx.\n", desc.dwFlags);
12933 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
12934 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
12935 "Got unexpected caps %#lx.\n", desc.ddsCaps.dwCaps);
12936 ok(desc.dwWidth == 256, "Got unexpected width %lu.\n", desc.dwWidth);
12937 ok(desc.dwHeight == 256, "Got unexpected height %lu.\n", desc.dwHeight);
12938 /* The overlay pitch seems to have 256 byte alignment. */
12939 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %lu.\n", U1(desc).lPitch);
12941 /* Fill the surface with some data for the blit test. */
12942 base = desc.lpSurface;
12943 /* Luminance */
12944 for (y = 0; y < desc.dwHeight; ++y)
12946 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
12948 /* V */
12949 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
12951 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
12953 /* U */
12954 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
12956 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
12959 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
12960 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12962 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
12963 * other block-based formats like DXT the entire Y channel is stored in
12964 * one big chunk of memory, followed by the chroma channels. So partial
12965 * locks do not really make sense. Show that they are allowed nevertheless
12966 * and the offset points into the luminance data. */
12967 hr = IDirectDrawSurface4_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
12968 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12969 offset = ((const unsigned char *)desc.lpSurface - base);
12970 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %lu.\n",
12971 offset, rect.top * U1(desc).lPitch + rect.left);
12972 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
12973 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
12975 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
12977 /* Windows XP with a Radeon X1600 GPU refuses to create a second
12978 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
12979 skip("Failed to create a second YV12 surface, skipping blit test.\n");
12980 IDirectDrawSurface4_Release(src_surface);
12981 goto done;
12984 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
12985 /* VMware rejects YV12 blits. This behavior has not been seen on real
12986 * hardware yet, so mark it broken. */
12987 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#lx.\n", hr);
12989 if (SUCCEEDED(hr))
12991 memset(&desc, 0, sizeof(desc));
12992 desc.dwSize = sizeof(desc);
12993 hr = IDirectDrawSurface4_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
12994 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
12996 base = desc.lpSurface;
12997 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
12998 base += desc.dwHeight * U1(desc).lPitch;
12999 ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
13000 base += desc.dwHeight / 4 * U1(desc).lPitch;
13001 ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
13003 hr = IDirectDrawSurface4_Unlock(dst_surface, NULL);
13004 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
13007 IDirectDrawSurface4_Release(dst_surface);
13008 IDirectDrawSurface4_Release(src_surface);
13009 done:
13010 IDirectDraw4_Release(ddraw);
13011 DestroyWindow(window);
13014 static BOOL dwm_enabled(void)
13016 BOOL ret = FALSE;
13018 if (!strcmp(winetest_platform, "wine"))
13019 return FALSE;
13020 if (!pDwmIsCompositionEnabled)
13021 return FALSE;
13022 if (FAILED(pDwmIsCompositionEnabled(&ret)))
13023 return FALSE;
13024 return ret;
13027 static void test_offscreen_overlay(void)
13029 IDirectDrawSurface4 *overlay, *offscreen, *primary;
13030 DDSURFACEDESC2 surface_desc;
13031 IDirectDraw4 *ddraw;
13032 HWND window;
13033 HRESULT hr;
13034 HDC dc;
13036 window = create_window();
13037 ddraw = create_ddraw();
13038 ok(!!ddraw, "Failed to create a ddraw object.\n");
13039 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13040 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
13042 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
13044 skip("Failed to create a UYVY overlay, skipping test.\n");
13045 goto done;
13048 memset(&surface_desc, 0, sizeof(surface_desc));
13049 surface_desc.dwSize = sizeof(surface_desc);
13050 surface_desc.dwFlags = DDSD_CAPS;
13051 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
13052 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
13053 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
13055 /* On Windows 7, and probably Vista, UpdateOverlay() will return
13056 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
13057 * surface prevents this by disabling the dwm. */
13058 hr = IDirectDrawSurface4_GetDC(primary, &dc);
13059 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
13060 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
13061 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
13063 /* Try to overlay a NULL surface. */
13064 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
13065 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13066 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
13067 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13069 /* Try to overlay an offscreen surface. */
13070 memset(&surface_desc, 0, sizeof(surface_desc));
13071 surface_desc.dwSize = sizeof(surface_desc);
13072 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
13073 surface_desc.dwWidth = 64;
13074 surface_desc.dwHeight = 64;
13075 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13076 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
13077 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
13078 U4(surface_desc).ddpfPixelFormat.dwFourCC = 0;
13079 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
13080 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
13081 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
13082 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
13083 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
13084 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
13086 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
13087 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled())
13088 || broken(hr == E_NOTIMPL && ddraw_is_vmware(ddraw)),
13089 "Failed to update overlay, hr %#lx.\n", hr);
13091 /* Try to overlay the primary with a non-overlay surface. */
13092 hr = IDirectDrawSurface4_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
13093 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#lx.\n", hr);
13094 hr = IDirectDrawSurface4_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
13095 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#lx.\n", hr);
13097 IDirectDrawSurface4_Release(offscreen);
13098 IDirectDrawSurface4_Release(primary);
13099 IDirectDrawSurface4_Release(overlay);
13100 done:
13101 IDirectDraw4_Release(ddraw);
13102 DestroyWindow(window);
13105 static void test_overlay_rect(void)
13107 IDirectDrawSurface4 *overlay, *primary = NULL;
13108 DDSURFACEDESC2 surface_desc;
13109 RECT rect = {0, 0, 64, 64};
13110 IDirectDraw4 *ddraw;
13111 LONG pos_x, pos_y;
13112 HRESULT hr, hr2;
13113 HWND window;
13114 HDC dc;
13116 window = create_window();
13117 ddraw = create_ddraw();
13118 ok(!!ddraw, "Failed to create a ddraw object.\n");
13119 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13120 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
13122 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
13124 skip("Failed to create a UYVY overlay, skipping test.\n");
13125 goto done;
13128 memset(&surface_desc, 0, sizeof(surface_desc));
13129 surface_desc.dwSize = sizeof(surface_desc);
13130 surface_desc.dwFlags = DDSD_CAPS;
13131 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
13132 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
13133 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n",hr);
13135 /* On Windows 7, and probably Vista, UpdateOverlay() will return
13136 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
13137 * surface prevents this by disabling the dwm. */
13138 hr = IDirectDrawSurface4_GetDC(primary, &dc);
13139 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
13140 hr = IDirectDrawSurface4_ReleaseDC(primary, dc);
13141 ok(SUCCEEDED(hr), "Failed to release DC, hr %#lx.\n", hr);
13143 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
13144 if (dwm_enabled())
13146 win_skip("Cannot disable DWM, skipping overlay test.\n");
13147 goto done;
13150 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
13151 * used. This is not true in Windows Vista and earlier, but changed in
13152 * Windows 7. */
13153 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
13154 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#lx.\n", hr);
13155 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
13156 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#lx.\n", hr);
13157 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
13158 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
13160 /* Show that the overlay position is the (top, left) coordinate of the
13161 * destination rectangle. */
13162 OffsetRect(&rect, 32, 16);
13163 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
13164 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#lx.\n", hr);
13165 pos_x = -1; pos_y = -1;
13166 hr = IDirectDrawSurface4_GetOverlayPosition(overlay, &pos_x, &pos_y);
13167 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#lx.\n", hr);
13168 ok(pos_x == rect.left, "Got unexpected pos_x %ld, expected %ld.\n", pos_x, rect.left);
13169 ok(pos_y == rect.top, "Got unexpected pos_y %ld, expected %ld.\n", pos_y, rect.top);
13171 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
13172 * seen that the overlay overlays the whole primary(==screen). */
13173 hr2 = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
13174 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#lx.\n", hr2);
13175 hr = IDirectDrawSurface4_GetOverlayPosition(overlay, &pos_x, &pos_y);
13176 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#lx.\n", hr);
13177 if (SUCCEEDED(hr2))
13179 ok(!pos_x, "Got unexpected pos_x %ld.\n", pos_x);
13180 ok(!pos_y, "Got unexpected pos_y %ld.\n", pos_y);
13182 else
13184 ok(pos_x == 32, "Got unexpected pos_x %ld.\n", pos_x);
13185 ok(pos_y == 16, "Got unexpected pos_y %ld.\n", pos_y);
13188 /* The position cannot be retrieved when the overlay is not shown. */
13189 hr = IDirectDrawSurface4_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
13190 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#lx.\n", hr);
13191 pos_x = -1; pos_y = -1;
13192 hr = IDirectDrawSurface4_GetOverlayPosition(overlay, &pos_x, &pos_y);
13193 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#lx.\n", hr);
13194 ok(!pos_x, "Got unexpected pos_x %ld.\n", pos_x);
13195 ok(!pos_y, "Got unexpected pos_y %ld.\n", pos_y);
13197 done:
13198 if (primary)
13199 IDirectDrawSurface4_Release(primary);
13200 if (overlay)
13201 IDirectDrawSurface4_Release(overlay);
13202 IDirectDraw4_Release(ddraw);
13203 DestroyWindow(window);
13206 static void test_blt(void)
13208 IDirectDrawSurface4 *surface, *rt;
13209 DDSURFACEDESC2 surface_desc;
13210 IDirect3DDevice3 *device;
13211 IDirectDraw4 *ddraw;
13212 IDirect3D3 *d3d;
13213 unsigned int i;
13214 ULONG refcount;
13215 HWND window;
13216 HRESULT hr;
13218 static struct
13220 RECT src_rect;
13221 RECT dst_rect;
13222 HRESULT hr;
13224 test_data[] =
13226 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
13227 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
13228 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
13229 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
13230 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
13231 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
13232 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
13233 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
13234 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
13235 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
13238 window = create_window();
13239 if (!(device = create_device(window, DDSCL_NORMAL)))
13241 skip("Failed to create a 3D device, skipping test.\n");
13242 DestroyWindow(window);
13243 return;
13246 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
13247 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#lx.\n", hr);
13248 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
13249 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#lx.\n", hr);
13250 IDirect3D3_Release(d3d);
13251 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
13252 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
13254 memset(&surface_desc, 0, sizeof(surface_desc));
13255 surface_desc.dwSize = sizeof(surface_desc);
13256 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
13257 surface_desc.dwWidth = 640;
13258 surface_desc.dwHeight = 480;
13259 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13260 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13261 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
13263 hr = IDirectDrawSurface4_Blt(surface, NULL, surface, NULL, 0, NULL);
13264 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
13266 hr = IDirectDrawSurface4_Blt(surface, NULL, rt, NULL, 0, NULL);
13267 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
13269 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
13271 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect,
13272 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
13273 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n", i, hr, test_data[i].hr);
13275 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect,
13276 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
13277 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n", i, hr, test_data[i].hr);
13279 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect,
13280 NULL, &test_data[i].src_rect, DDBLT_WAIT, NULL);
13281 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#lx.\n", i, hr);
13283 hr = IDirectDrawSurface4_Blt(surface, &test_data[i].dst_rect, NULL, NULL, DDBLT_WAIT, NULL);
13284 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#lx.\n", i, hr);
13287 IDirectDrawSurface4_Release(surface);
13288 IDirectDrawSurface4_Release(rt);
13289 IDirectDraw4_Release(ddraw);
13290 refcount = IDirect3DDevice3_Release(device);
13291 ok(!refcount, "Device has %lu references left.\n", refcount);
13292 DestroyWindow(window);
13295 static void test_blt_z_alpha(void)
13297 DWORD blt_flags[] =
13299 /* 0 */
13300 DDBLT_ALPHADEST,
13301 DDBLT_ALPHADESTCONSTOVERRIDE,
13302 DDBLT_ALPHADESTNEG,
13303 DDBLT_ALPHADESTSURFACEOVERRIDE,
13304 DDBLT_ALPHAEDGEBLEND,
13305 /* 5 */
13306 DDBLT_ALPHASRC,
13307 DDBLT_ALPHASRCCONSTOVERRIDE,
13308 DDBLT_ALPHASRCNEG,
13309 DDBLT_ALPHASRCSURFACEOVERRIDE,
13310 DDBLT_ZBUFFER,
13311 /* 10 */
13312 DDBLT_ZBUFFERDESTCONSTOVERRIDE,
13313 DDBLT_ZBUFFERDESTOVERRIDE,
13314 DDBLT_ZBUFFERSRCCONSTOVERRIDE,
13315 DDBLT_ZBUFFERSRCOVERRIDE,
13317 IDirectDrawSurface4 *src_surface, *dst_surface;
13318 DDSURFACEDESC2 surface_desc;
13319 unsigned int color, i;
13320 IDirectDraw4 *ddraw;
13321 DDPIXELFORMAT pf;
13322 ULONG refcount;
13323 HWND window;
13324 HRESULT hr;
13325 DDBLTFX fx;
13327 window = create_window();
13328 ddraw = create_ddraw();
13329 ok(!!ddraw, "Failed to create a ddraw object.\n");
13330 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13331 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
13333 memset(&pf, 0, sizeof(pf));
13334 pf.dwSize = sizeof(pf);
13335 pf.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
13336 U1(pf).dwRGBBitCount = 32;
13337 U2(pf).dwRBitMask = 0x00ff0000;
13338 U3(pf).dwGBitMask = 0x0000ff00;
13339 U4(pf).dwBBitMask = 0x000000ff;
13340 U5(pf).dwRGBAlphaBitMask = 0xff000000;
13342 memset(&surface_desc, 0, sizeof(surface_desc));
13343 surface_desc.dwSize = sizeof(surface_desc);
13344 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
13345 surface_desc.dwWidth = 64;
13346 surface_desc.dwHeight = 64;
13347 U4(surface_desc).ddpfPixelFormat = pf;
13348 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13350 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
13351 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#lx.\n", hr);
13352 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
13353 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#lx.\n", hr);
13355 memset(&fx, 0, sizeof(fx));
13356 fx.dwSize = sizeof(fx);
13357 fx.dwZBufferOpCode = D3DCMP_NEVER;
13358 fx.dwZDestConstBitDepth = 32;
13359 U1(fx).dwZDestConst = 0x11111111;
13360 fx.dwZSrcConstBitDepth = 32;
13361 U2(fx).dwZSrcConst = 0xeeeeeeee;
13362 fx.dwAlphaEdgeBlendBitDepth = 8;
13363 fx.dwAlphaEdgeBlend = 0x7f;
13364 fx.dwAlphaDestConstBitDepth = 8;
13365 U3(fx).dwAlphaDestConst = 0xdd;
13366 fx.dwAlphaSrcConstBitDepth = 8;
13367 U4(fx).dwAlphaSrcConst = 0x22;
13369 for (i = 0; i < ARRAY_SIZE(blt_flags); ++i)
13371 U5(fx).dwFillColor = 0x3300ff00;
13372 hr = IDirectDrawSurface4_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
13373 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#lx.\n", i, hr);
13375 U5(fx).dwFillColor = 0xccff0000;
13376 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
13377 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#lx.\n", i, hr);
13379 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, NULL, blt_flags[i] | DDBLT_WAIT, &fx);
13380 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#lx.\n", i, hr);
13382 color = get_surface_color(dst_surface, 32, 32);
13383 ok(compare_color(color, 0x0000ff00, 0), "Test %u: Got unexpected color 0x%08x.\n", i, color);
13386 IDirectDrawSurface4_Release(dst_surface);
13387 IDirectDrawSurface4_Release(src_surface);
13388 refcount = IDirectDraw4_Release(ddraw);
13389 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
13390 DestroyWindow(window);
13393 static void test_cross_device_blt(void)
13395 IDirectDrawSurface4 *surface, *surface2, *sysmem_surface;
13396 IDirect3DDevice3 *device, *device2;
13397 IDirectDraw4 *ddraw, *ddraw2;
13398 DDSURFACEDESC2 surface_desc;
13399 HWND window, window2;
13400 unsigned int color;
13401 IDirect3D3 *d3d;
13402 ULONG refcount;
13403 DDBLTFX fx;
13404 HRESULT hr;
13406 window = create_window();
13407 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
13409 skip("Failed to create a 3D device.\n");
13410 DestroyWindow(window);
13411 return;
13414 window2 = create_window();
13415 if (!(device2 = create_device(window2, DDSCL_NORMAL)))
13417 skip("Failed to create a 3D device.\n");
13418 IDirect3DDevice3_Release(device);
13419 DestroyWindow(window);
13420 DestroyWindow(window2);
13421 return;
13424 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
13425 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#lx.\n", hr);
13426 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
13427 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#lx.\n", hr);
13428 IDirect3D3_Release(d3d);
13430 hr = IDirect3DDevice3_GetDirect3D(device2, &d3d);
13431 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#lx.\n", hr);
13432 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw2);
13433 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#lx.\n", hr);
13434 IDirect3D3_Release(d3d);
13436 memset(&surface_desc, 0, sizeof(surface_desc));
13437 surface_desc.dwSize = sizeof(surface_desc);
13438 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
13439 surface_desc.dwWidth = 640;
13440 surface_desc.dwHeight = 480;
13441 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
13442 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
13443 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
13445 memset(&surface_desc, 0, sizeof(surface_desc));
13446 surface_desc.dwSize = sizeof(surface_desc);
13447 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
13448 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
13449 U5(surface_desc).dwBackBufferCount = 2;
13450 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13451 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
13453 memset(&surface_desc, 0, sizeof(surface_desc));
13454 surface_desc.dwSize = sizeof(surface_desc);
13455 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
13456 surface_desc.dwWidth = 640;
13457 surface_desc.dwHeight = 480;
13458 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
13459 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
13460 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
13461 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
13462 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00007c00;
13463 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x000003e0;
13464 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000001f;
13465 hr = IDirectDraw4_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
13466 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
13468 memset(&fx, 0, sizeof(fx));
13469 fx.dwSize = sizeof(fx);
13470 U5(fx).dwFillColor = 0xff0000ff;
13471 hr = IDirectDrawSurface4_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
13472 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#lx.\n", hr);
13474 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
13475 ok(hr == E_NOTIMPL, "Got unexpected hr %#lx.\n", hr);
13476 hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
13477 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
13478 hr = IDirectDrawSurface4_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
13479 ok(hr == E_NOTIMPL, "Got unexpected hr %#lx.\n", hr);
13480 color = get_surface_color(surface, 320, 240);
13481 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
13483 hr = IDirectDrawSurface4_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
13484 ok(hr == E_NOTIMPL, "Got unexpected hr %#lx.\n", hr);
13485 color = get_surface_color(sysmem_surface, 320, 240);
13486 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
13488 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13489 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
13490 hr = IDirectDrawSurface4_IsLost(sysmem_surface);
13491 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
13493 hr = IDirectDrawSurface4_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
13494 ok(hr == E_NOTIMPL, "Got unexpected hr %#lx.\n", hr);
13495 color = get_surface_color(sysmem_surface, 320, 240);
13496 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
13498 IDirectDrawSurface4_Release(surface2);
13499 memset(&surface_desc, 0, sizeof(surface_desc));
13500 surface_desc.dwSize = sizeof(surface_desc);
13501 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
13502 surface_desc.dwWidth = 640;
13503 surface_desc.dwHeight = 480;
13504 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
13505 hr = IDirectDraw4_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
13506 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
13507 hr = IDirectDrawSurface4_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
13508 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#lx.\n", hr);
13510 hr = IDirectDrawSurface4_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
13511 todo_wine ok(hr == D3D_OK, "Failed to blit, hr %#lx.\n", hr);
13512 color = get_surface_color(sysmem_surface, 320, 240);
13513 todo_wine ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
13515 IDirectDrawSurface4_Release(surface);
13516 IDirectDrawSurface4_Release(surface2);
13517 IDirectDrawSurface4_Release(sysmem_surface);
13518 IDirectDraw4_Release(ddraw);
13519 IDirectDraw4_Release(ddraw2);
13520 refcount = IDirect3DDevice3_Release(device);
13521 ok(!refcount, "Device has %lu references left.\n", refcount);
13522 refcount = IDirect3DDevice3_Release(device2);
13523 ok(!refcount, "Device has %lu references left.\n", refcount);
13524 DestroyWindow(window);
13525 DestroyWindow(window2);
13528 static void test_color_clamping(void)
13530 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
13531 static D3DMATRIX mat =
13533 1.0f, 0.0f, 0.0f, 0.0f,
13534 0.0f, 1.0f, 0.0f, 0.0f,
13535 0.0f, 0.0f, 1.0f, 0.0f,
13536 0.0f, 0.0f, 0.0f, 1.0f,
13538 static struct vec3 quad[] =
13540 {-1.0f, -1.0f, 0.1f},
13541 {-1.0f, 1.0f, 0.1f},
13542 { 1.0f, -1.0f, 0.1f},
13543 { 1.0f, 1.0f, 0.1f},
13545 IDirect3DViewport3 *viewport;
13546 IDirect3DDevice3 *device;
13547 IDirectDrawSurface4 *rt;
13548 unsigned int color;
13549 ULONG refcount;
13550 HWND window;
13551 HRESULT hr;
13553 window = create_window();
13554 if (!(device = create_device(window, DDSCL_NORMAL)))
13556 skip("Failed to create a 3D device, skipping test.\n");
13557 DestroyWindow(window);
13558 return;
13561 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
13562 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
13564 viewport = create_viewport(device, 0, 0, 640, 480);
13565 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
13566 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#lx.\n", hr);
13568 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
13569 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
13570 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
13571 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#lx.\n", hr);
13572 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
13573 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#lx.\n", hr);
13574 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
13575 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#lx.\n", hr);
13576 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
13577 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#lx.\n", hr);
13578 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
13579 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#lx.\n", hr);
13580 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
13581 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#lx.\n", hr);
13583 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0xff404040);
13584 ok(SUCCEEDED(hr), "Failed to set texture factor, hr %#lx.\n", hr);
13585 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
13586 ok(SUCCEEDED(hr), "Failed to set color op, hr %#lx.\n", hr);
13587 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
13588 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#lx.\n", hr);
13589 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
13590 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#lx.\n", hr);
13591 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
13592 ok(SUCCEEDED(hr), "Failed to set color op, hr %#lx.\n", hr);
13593 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
13594 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#lx.\n", hr);
13595 hr = IDirect3DDevice3_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
13596 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#lx.\n", hr);
13598 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
13599 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
13601 hr = IDirect3DDevice3_BeginScene(device);
13602 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
13604 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
13605 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
13607 hr = IDirect3DDevice3_EndScene(device);
13608 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
13610 color = get_surface_color(rt, 320, 240);
13611 ok(compare_color(color, 0x00404040, 1), "Got unexpected color 0x%08x.\n", color);
13613 destroy_viewport(device, viewport);
13614 IDirectDrawSurface4_Release(rt);
13615 refcount = IDirect3DDevice3_Release(device);
13616 ok(!refcount, "Device has %lu references left.\n", refcount);
13617 DestroyWindow(window);
13620 static void test_getdc(void)
13622 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
13623 IDirectDrawSurface4 *surface, *surface2, *tmp;
13624 DDSURFACEDESC2 surface_desc, map_desc;
13625 IDirectDraw4 *ddraw;
13626 unsigned int i, screen_bpp;
13627 HWND window;
13628 HDC dc, dc2;
13629 HRESULT hr;
13631 static const struct
13633 const char *name;
13634 DDPIXELFORMAT format;
13635 BOOL getdc_supported;
13636 HRESULT alt_result;
13638 test_data[] =
13640 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
13641 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
13642 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
13643 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
13644 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
13645 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
13646 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
13647 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
13648 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
13649 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
13650 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
13651 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
13652 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
13653 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
13654 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
13655 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
13656 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
13657 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
13658 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
13659 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
13660 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
13661 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
13662 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
13663 * This is not implemented in wine yet, so disable the test for now.
13664 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
13665 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
13666 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13668 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
13669 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13670 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
13671 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
13672 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
13673 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13674 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
13675 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13676 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
13677 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13678 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
13679 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13680 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
13681 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13684 window = create_window();
13685 ddraw = create_ddraw();
13686 ok(!!ddraw, "Failed to create a ddraw object.\n");
13687 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13688 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
13690 surface_desc.dwSize = sizeof(surface_desc);
13691 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
13692 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#lx.\n", hr);
13693 screen_bpp = U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount;
13695 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
13697 memset(&surface_desc, 0, sizeof(surface_desc));
13698 surface_desc.dwSize = sizeof(surface_desc);
13699 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13700 surface_desc.dwWidth = 64;
13701 surface_desc.dwHeight = 64;
13702 U4(surface_desc).ddpfPixelFormat = test_data[i].format;
13703 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13705 if (FAILED(IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
13707 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
13708 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
13709 if (FAILED(hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
13711 skip("Failed to create surface for format %s (hr %#lx), skipping tests.\n", test_data[i].name, hr);
13712 continue;
13716 dc = (void *)0x1234;
13717 hr = IDirectDrawSurface4_GetDC(surface, &dc);
13718 if (test_data[i].getdc_supported)
13719 ok(SUCCEEDED(hr) || broken(hr == test_data[i].alt_result),
13720 "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
13721 else
13722 ok(FAILED(hr), "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
13724 if (SUCCEEDED(hr))
13726 unsigned int width_bytes;
13727 DIBSECTION dib;
13728 HBITMAP bitmap;
13729 DWORD type;
13730 int size;
13732 type = GetObjectType(dc);
13733 ok(type == OBJ_MEMDC, "Got unexpected object type %#lx for format %s.\n", type, test_data[i].name);
13734 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
13735 type = GetObjectType(bitmap);
13736 ok(type == OBJ_BITMAP, "Got unexpected object type %#lx for format %s.\n", type, test_data[i].name);
13738 size = GetObjectA(bitmap, sizeof(dib), &dib);
13739 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
13740 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
13741 dib.dsBm.bmType, test_data[i].name);
13742 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
13743 dib.dsBm.bmWidth, test_data[i].name);
13744 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
13745 dib.dsBm.bmHeight, test_data[i].name);
13746 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
13747 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
13748 dib.dsBm.bmWidthBytes, test_data[i].name);
13749 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
13750 dib.dsBm.bmPlanes, test_data[i].name);
13751 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
13752 "Got unexpected bit count %d for format %s.\n",
13753 dib.dsBm.bmBitsPixel, test_data[i].name);
13754 /* Windows XP sets bmBits == NULL for formats that match the screen at least on my r200 GPU. I
13755 * suspect this applies to all HW accelerated pre-WDDM drivers because they can handle gdi access
13756 * to ddraw surfaces themselves instead of going through a sysmem DIB section. */
13757 ok(!!dib.dsBm.bmBits || broken(!pDwmIsCompositionEnabled && dib.dsBm.bmBitsPixel == screen_bpp),
13758 "Got unexpected bits %p for format %s.\n", dib.dsBm.bmBits, test_data[i].name);
13760 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %lu for format %s.\n",
13761 dib.dsBmih.biSize, test_data[i].name);
13762 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %ld for format %s.\n",
13763 dib.dsBmih.biHeight, test_data[i].name);
13764 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %ld for format %s.\n",
13765 dib.dsBmih.biHeight, test_data[i].name);
13766 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
13767 dib.dsBmih.biPlanes, test_data[i].name);
13768 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
13769 "Got unexpected bit count %u for format %s.\n",
13770 dib.dsBmih.biBitCount, test_data[i].name);
13771 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
13772 || broken(U1(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
13773 "Got unexpected compression %#lx for format %s.\n",
13774 dib.dsBmih.biCompression, test_data[i].name);
13775 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %lu for format %s.\n",
13776 dib.dsBmih.biSizeImage, test_data[i].name);
13777 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %ld for format %s.\n",
13778 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
13779 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %ld for format %s.\n",
13780 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
13781 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %lu for format %s.\n",
13782 dib.dsBmih.biClrUsed, test_data[i].name);
13783 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %lu for format %s.\n",
13784 dib.dsBmih.biClrImportant, test_data[i].name);
13786 if (dib.dsBmih.biCompression == BI_BITFIELDS)
13788 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
13789 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
13790 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
13791 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
13792 "Got unexpected colour masks 0x%08lx 0x%08lx 0x%08lx for format %s.\n",
13793 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
13795 else
13797 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
13798 "Got unexpected colour masks 0x%08lx 0x%08lx 0x%08lx for format %s.\n",
13799 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
13801 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
13802 ok(!dib.dsOffset, "Got unexpected offset %lu for format %s.\n", dib.dsOffset, test_data[i].name);
13804 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
13805 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13807 else
13809 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
13812 IDirectDrawSurface4_Release(surface);
13814 if (FAILED(hr))
13815 continue;
13817 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
13818 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
13819 if (FAILED(hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
13821 skip("Failed to create mip-mapped texture for format %s (hr %#lx), skipping tests.\n",
13822 test_data[i].name, hr);
13823 continue;
13826 hr = IDirectDrawSurface4_GetAttachedSurface(surface, &caps, &tmp);
13827 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13828 hr = IDirectDrawSurface4_GetAttachedSurface(tmp, &caps, &surface2);
13829 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13830 IDirectDrawSurface4_Release(tmp);
13832 hr = IDirectDrawSurface4_GetDC(surface, &dc);
13833 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13834 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
13835 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13836 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
13837 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13838 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
13839 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13841 hr = IDirectDrawSurface4_GetDC(surface, &dc);
13842 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13843 dc2 = (void *)0x1234;
13844 hr = IDirectDrawSurface4_GetDC(surface, &dc2);
13845 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
13846 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
13847 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
13848 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13849 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
13850 ok(hr == DDERR_NODC, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
13852 map_desc.dwSize = sizeof(map_desc);
13853 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13854 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13855 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13856 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
13857 hr = IDirectDrawSurface4_Unlock(surface, NULL);
13858 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13859 hr = IDirectDrawSurface4_Unlock(surface, NULL);
13860 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
13862 hr = IDirectDrawSurface4_GetDC(surface, &dc);
13863 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13864 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13865 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
13866 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
13867 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13869 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13870 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13871 hr = IDirectDrawSurface4_GetDC(surface, &dc);
13872 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13873 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
13874 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13875 hr = IDirectDrawSurface4_Unlock(surface, NULL);
13876 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13878 hr = IDirectDrawSurface4_GetDC(surface, &dc);
13879 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13880 hr = IDirectDrawSurface4_GetDC(surface2, &dc2);
13881 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13882 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc2);
13883 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13884 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
13885 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13887 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
13888 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13889 hr = IDirectDrawSurface4_GetDC(surface, &dc2);
13890 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13891 hr = IDirectDrawSurface4_ReleaseDC(surface, dc2);
13892 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13893 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
13894 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13896 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13897 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13898 hr = IDirectDrawSurface4_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13899 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13900 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
13901 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13902 hr = IDirectDrawSurface4_Unlock(surface, NULL);
13903 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13905 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13906 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13907 hr = IDirectDrawSurface4_GetDC(surface, &dc);
13908 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13909 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
13910 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13911 hr = IDirectDrawSurface4_Unlock(surface, NULL);
13912 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13914 hr = IDirectDrawSurface4_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13915 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13916 hr = IDirectDrawSurface4_GetDC(surface, &dc);
13917 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13918 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
13919 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13920 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
13921 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13923 hr = IDirectDrawSurface4_GetDC(surface, &dc);
13924 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13925 hr = IDirectDrawSurface4_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13926 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13927 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
13928 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13929 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
13930 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13932 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
13933 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13934 hr = IDirectDrawSurface4_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13935 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13936 hr = IDirectDrawSurface4_Unlock(surface, NULL);
13937 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#lx.\n", test_data[i].name, hr);
13938 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
13939 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13941 hr = IDirectDrawSurface4_Unlock(surface, NULL);
13942 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
13943 hr = IDirectDrawSurface4_GetDC(surface2, &dc);
13944 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13945 hr = IDirectDrawSurface4_Unlock(surface, NULL);
13946 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
13947 hr = IDirectDrawSurface4_ReleaseDC(surface2, dc);
13948 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13949 hr = IDirectDrawSurface4_Unlock(surface, NULL);
13950 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
13952 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
13953 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
13954 hr = IDirectDrawSurface4_GetDC(surface, &dc);
13955 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13956 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
13957 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
13958 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
13959 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#lx.\n", test_data[i].name, hr);
13960 hr = IDirectDrawSurface4_Unlock(surface2, NULL);
13961 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#lx for format %s.\n", hr, test_data[i].name);
13963 IDirectDrawSurface4_Release(surface2);
13964 IDirectDrawSurface4_Release(surface);
13967 IDirectDraw4_Release(ddraw);
13968 DestroyWindow(window);
13971 static void test_draw_primitive(void)
13973 static WORD indices[] = {0, 1, 2, 3};
13974 static struct vec3 quad[] =
13976 {-1.0f, -1.0f, 0.0f},
13977 {-1.0f, 1.0f, 0.0f},
13978 { 1.0f, -1.0f, 0.0f},
13979 { 1.0f, 1.0f, 0.0f},
13981 D3DDRAWPRIMITIVESTRIDEDDATA strided;
13982 IDirect3DViewport3 *viewport;
13983 D3DVERTEXBUFFERDESC vb_desc;
13984 IDirect3DVertexBuffer *vb;
13985 IDirect3DDevice3 *device;
13986 IDirect3D3 *d3d;
13987 ULONG refcount;
13988 HWND window;
13989 HRESULT hr;
13990 void *data;
13992 window = create_window();
13993 if (!(device = create_device(window, DDSCL_NORMAL)))
13995 skip("Failed to create a 3D device, skipping test.\n");
13996 DestroyWindow(window);
13997 return;
14000 viewport = create_viewport(device, 0, 0, 640, 480);
14001 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
14002 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#lx.\n", hr);
14004 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
14005 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#lx.\n", hr);
14007 memset(&vb_desc, 0, sizeof(vb_desc));
14008 vb_desc.dwSize = sizeof(vb_desc);
14009 vb_desc.dwFVF = D3DFVF_XYZ;
14010 vb_desc.dwNumVertices = 4;
14011 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &vb, 0, NULL);
14012 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#lx.\n", hr);
14014 IDirect3D3_Release(d3d);
14016 memset(&strided, 0, sizeof(strided));
14018 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
14019 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14020 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
14021 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, NULL, 0, 0);
14022 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14023 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, NULL, 0, 0);
14024 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14025 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
14026 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14027 hr = IDirect3DDevice3_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, 0);
14028 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14029 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, 0);
14030 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14032 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
14033 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14034 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
14035 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, indices, 4, 0);
14036 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14037 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, indices, 4, 0);
14038 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14040 strided.position.lpvData = quad;
14041 strided.position.dwStride = sizeof(*quad);
14042 hr = IDirect3DVertexBuffer_Lock(vb, 0, &data, NULL);
14043 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#lx.\n", hr);
14044 memcpy(data, quad, sizeof(quad));
14045 hr = IDirect3DVertexBuffer_Unlock(vb);
14046 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#lx.\n", hr);
14048 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
14049 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14050 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
14051 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, NULL, 0, 0);
14052 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14053 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, NULL, 0, 0);
14054 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14055 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
14056 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14057 hr = IDirect3DDevice3_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, 0);
14058 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14059 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
14060 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14061 hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
14062 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14063 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device,
14064 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, indices, 4, 0);
14065 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14066 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, indices, 4, 0);
14067 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14069 IDirect3DVertexBuffer_Release(vb);
14070 destroy_viewport(device, viewport);
14071 refcount = IDirect3DDevice3_Release(device);
14072 ok(!refcount, "Device has %lu references left.\n", refcount);
14073 DestroyWindow(window);
14076 static void test_edge_antialiasing_blending(void)
14078 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
14079 IDirectDrawSurface4 *offscreen, *ds;
14080 D3DDEVICEDESC hal_desc, hel_desc;
14081 IDirect3DViewport3 *viewport;
14082 DDSURFACEDESC2 surface_desc;
14083 IDirect3DDevice3 *device;
14084 IDirectDraw4 *ddraw;
14085 unsigned int color;
14086 IDirect3D3 *d3d;
14087 ULONG refcount;
14088 HWND window;
14089 HRESULT hr;
14091 static D3DMATRIX mat =
14093 1.0f, 0.0f, 0.0f, 0.0f,
14094 0.0f, 1.0f, 0.0f, 0.0f,
14095 0.0f, 0.0f, 1.0f, 0.0f,
14096 0.0f, 0.0f, 0.0f, 1.0f,
14098 static struct
14100 struct vec3 position;
14101 DWORD diffuse;
14103 green_quad[] =
14105 {{-1.0f, -1.0f, 0.1f}, 0x7f00ff00},
14106 {{-1.0f, 1.0f, 0.1f}, 0x7f00ff00},
14107 {{ 1.0f, -1.0f, 0.1f}, 0x7f00ff00},
14108 {{ 1.0f, 1.0f, 0.1f}, 0x7f00ff00},
14110 static struct
14112 struct vec3 position;
14113 DWORD diffuse;
14115 red_quad[] =
14117 {{-1.0f, -1.0f, 0.1f}, 0xccff0000},
14118 {{-1.0f, 1.0f, 0.1f}, 0xccff0000},
14119 {{ 1.0f, -1.0f, 0.1f}, 0xccff0000},
14120 {{ 1.0f, 1.0f, 0.1f}, 0xccff0000},
14123 window = create_window();
14124 if (!(device = create_device(window, DDSCL_NORMAL)))
14126 skip("Failed to create a 3D device.\n");
14127 DestroyWindow(window);
14128 return;
14131 memset(&hal_desc, 0, sizeof(hal_desc));
14132 hal_desc.dwSize = sizeof(hal_desc);
14133 memset(&hel_desc, 0, sizeof(hel_desc));
14134 hel_desc.dwSize = sizeof(hel_desc);
14135 hr = IDirect3DDevice3_GetCaps(device, &hal_desc, &hel_desc);
14136 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#lx.\n", hr);
14137 trace("HAL line edge antialiasing support: %#lx.\n",
14138 hal_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
14139 trace("HAL triangle edge antialiasing support: %#lx.\n",
14140 hal_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
14141 trace("HEL line edge antialiasing support: %#lx.\n",
14142 hel_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
14143 trace("HEL triangle edge antialiasing support: %#lx.\n",
14144 hel_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
14146 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
14147 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#lx.\n", hr);
14148 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
14149 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#lx.\n", hr);
14150 IDirect3D3_Release(d3d);
14152 memset(&surface_desc, 0, sizeof(surface_desc));
14153 surface_desc.dwSize = sizeof(surface_desc);
14154 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
14155 surface_desc.dwWidth = 640;
14156 surface_desc.dwHeight = 480;
14157 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
14158 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
14159 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
14160 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
14161 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
14162 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
14163 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
14164 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
14165 ok(hr == D3D_OK, "Creating the offscreen render target failed, hr %#lx.\n", hr);
14167 ds = get_depth_stencil(device);
14168 hr = IDirectDrawSurface4_AddAttachedSurface(offscreen, ds);
14169 todo_wine ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#lx.\n", hr);
14170 IDirectDrawSurface4_Release(ds);
14172 hr = IDirect3DDevice3_SetRenderTarget(device, offscreen, 0);
14173 ok(SUCCEEDED(hr), "Failed to set render target, hr %#lx.\n", hr);
14175 viewport = create_viewport(device, 0, 0, 640, 480);
14176 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
14177 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
14179 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
14180 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
14181 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
14182 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#lx.\n", hr);
14183 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
14184 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#lx.\n", hr);
14185 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
14186 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#lx.\n", hr);
14187 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
14188 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#lx.\n", hr);
14189 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
14190 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#lx.\n", hr);
14191 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
14192 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#lx.\n", hr);
14194 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
14195 ok(SUCCEEDED(hr), "Failed to enable blending, hr %#lx.\n", hr);
14196 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
14197 ok(SUCCEEDED(hr), "Failed to set src blend, hr %#lx.\n", hr);
14198 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
14199 ok(SUCCEEDED(hr), "Failed to set dest blend, hr %#lx.\n", hr);
14201 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
14202 ok(SUCCEEDED(hr), "Failed to set color op, hr %#lx.\n", hr);
14203 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
14204 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#lx.\n", hr);
14205 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
14206 ok(SUCCEEDED(hr), "Failed to set alpha op, hr %#lx.\n", hr);
14207 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
14208 ok(SUCCEEDED(hr), "Failed to set alpha arg, hr %#lx.\n", hr);
14210 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
14211 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
14212 hr = IDirect3DDevice3_BeginScene(device);
14213 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
14214 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14215 green_quad, 4, 0);
14216 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14217 hr = IDirect3DDevice3_EndScene(device);
14218 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
14219 color = get_surface_color(offscreen, 320, 240);
14220 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
14222 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
14223 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
14224 hr = IDirect3DDevice3_BeginScene(device);
14225 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
14226 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14227 red_quad, 4, 0);
14228 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14229 hr = IDirect3DDevice3_EndScene(device);
14230 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
14231 color = get_surface_color(offscreen, 320, 240);
14232 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
14234 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
14235 ok(SUCCEEDED(hr), "Failed to disable blending, hr %#lx.\n", hr);
14237 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
14238 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
14239 hr = IDirect3DDevice3_BeginScene(device);
14240 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
14241 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14242 green_quad, 4, 0);
14243 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14244 hr = IDirect3DDevice3_EndScene(device);
14245 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
14246 color = get_surface_color(offscreen, 320, 240);
14247 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
14249 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
14250 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
14251 hr = IDirect3DDevice3_BeginScene(device);
14252 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
14253 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14254 red_quad, 4, 0);
14255 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14256 hr = IDirect3DDevice3_EndScene(device);
14257 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
14258 color = get_surface_color(offscreen, 320, 240);
14259 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
14261 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_EDGEANTIALIAS, TRUE);
14262 ok(SUCCEEDED(hr), "Failed to enable edge antialiasing, hr %#lx.\n", hr);
14264 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
14265 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
14266 hr = IDirect3DDevice3_BeginScene(device);
14267 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
14268 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14269 green_quad, 4, 0);
14270 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14271 hr = IDirect3DDevice3_EndScene(device);
14272 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
14273 color = get_surface_color(offscreen, 320, 240);
14274 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
14276 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
14277 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
14278 hr = IDirect3DDevice3_BeginScene(device);
14279 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
14280 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14281 red_quad, 4, 0);
14282 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14283 hr = IDirect3DDevice3_EndScene(device);
14284 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
14285 color = get_surface_color(offscreen, 320, 240);
14286 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
14288 IDirectDrawSurface4_Release(offscreen);
14289 IDirectDraw4_Release(ddraw);
14290 destroy_viewport(device, viewport);
14291 refcount = IDirect3DDevice3_Release(device);
14292 ok(!refcount, "Device has %lu references left.\n", refcount);
14293 DestroyWindow(window);
14296 /* TransformVertices always writes 32 bytes regardless of the input / output stride.
14297 * The stride is honored for navigating to the next vertex. 3 floats input position
14298 * are read, and 16 bytes extra vertex data are copied around. */
14299 struct transform_input
14301 float x, y, z, unused1; /* Position data, transformed. */
14302 DWORD v1, v2, v3, v4; /* Extra data, e.g. color and texture coords, copied. */
14303 DWORD unused2;
14306 struct transform_output
14308 float x, y, z, w;
14309 unsigned int v1, v2, v3, v4;
14310 unsigned int unused3, unused4;
14313 static void test_transform_vertices(void)
14315 IDirect3DDevice3 *device;
14316 IDirectDrawSurface4 *rt;
14317 unsigned int color;
14318 ULONG refcount;
14319 HWND window;
14320 HRESULT hr;
14321 IDirect3DViewport3 *viewport;
14322 static struct transform_input position_tests[] =
14324 { 0.0f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
14325 { 1.0f, 1.0f, 1.0f, 8.0f, 6, 7, 8, 9, 10},
14326 {-1.0f, -1.0f, -1.0f, 4.0f, 11, 12, 13, 14, 15},
14327 { 0.5f, 0.5f, 0.5f, 2.0f, 16, 17, 18, 19, 20},
14328 {-0.5f, -0.5f, -0.5f, 1.0f, ~1U, ~2U, ~3U, ~4U, ~5U},
14329 {-0.5f, -0.5f, 0.0f, 0.0f, ~6U, ~7U, ~8U, ~9U, ~0U},
14331 static struct transform_input cliptest[] =
14333 { 25.59f, 25.59f, 1.0f, 0.0f, 1, 2, 3, 4, 5},
14334 { 25.61f, 25.61f, 1.01f, 0.0f, 1, 2, 3, 4, 5},
14335 {-25.59f, -25.59f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
14336 {-25.61f, -25.61f, -0.01f, 0.0f, 1, 2, 3, 4, 5},
14338 static struct transform_input offscreentest[] =
14340 {128.1f, 0.0f, 0.0f, 0.0f, 1, 2, 3, 4, 5},
14342 struct transform_output out[ARRAY_SIZE(position_tests)];
14343 D3DHVERTEX out_h[ARRAY_SIZE(position_tests)];
14344 D3DTRANSFORMDATA transformdata;
14345 static const D3DVIEWPORT vp_template =
14347 sizeof(vp_template), 0, 0, 256, 256, 5.0f, 5.0f, 256.0f, 256.0f, -25.0f, 60.0f
14349 D3DVIEWPORT vp_data =
14351 sizeof(vp_data), 0, 0, 256, 256, 1.0f, 1.0f, 256.0f, 256.0f, 0.0f, 1.0f
14353 D3DVIEWPORT2 vp2_data;
14354 unsigned int i;
14355 DWORD offscreen;
14356 static D3DMATRIX mat_scale =
14358 2.0f, 0.0f, 0.0f, 0.0f,
14359 0.0f, 2.0f, 0.0f, 0.0f,
14360 0.0f, 0.0f, 2.0f, 0.0f,
14361 0.0f, 0.0f, 0.0f, 1.0f,
14363 mat_translate1 =
14365 1.0f, 0.0f, 0.0f, 0.0f,
14366 0.0f, 1.0f, 0.0f, 0.0f,
14367 0.0f, 0.0f, 1.0f, 0.0f,
14368 1.0f, 0.0f, 0.0f, 1.0f,
14370 mat_translate2 =
14372 1.0f, 0.0f, 0.0f, 0.0f,
14373 0.0f, 1.0f, 0.0f, 0.0f,
14374 0.0f, 0.0f, 1.0f, 0.0f,
14375 0.0f, 1.0f, 0.0f, 1.0f,
14377 mat_transform3 =
14379 1.0f, 0.0f, 0.0f, 0.0f,
14380 0.0f, 1.0f, 0.0f, 0.0f,
14381 0.0f, 0.0f, 1.0f, 0.0f,
14382 0.0f, 19.2f, 0.0f, 2.0f,
14384 mat_identity =
14386 1.0f, 0.0f, 0.0f, 0.0f,
14387 0.0f, 1.0f, 0.0f, 0.0f,
14388 0.0f, 0.0f, 1.0f, 0.0f,
14389 0.0f, 0.0f, 0.0f, 1.0f,
14391 static struct
14393 struct vec3 position;
14394 DWORD color;
14396 quad[] =
14398 {{-0.75f, -0.5f , 0.0f}, 0xffff0000},
14399 {{-0.75f, 0.25f, 0.0f}, 0xffff0000},
14400 {{ 0.5f, -0.5f , 0.0f}, 0xffff0000},
14401 {{ 0.5f, 0.25f, 0.0f}, 0xffff0000},
14403 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
14405 for (i = 0; i < ARRAY_SIZE(out); ++i)
14407 out[i].unused3 = 0xdeadbeef;
14408 out[i].unused4 = 0xcafecafe;
14411 window = create_window();
14412 if (!(device = create_device(window, DDSCL_NORMAL)))
14414 skip("Failed to create a 3D device.\n");
14415 DestroyWindow(window);
14416 return;
14418 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
14419 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
14421 viewport = create_viewport(device, 0, 0, 256, 256);
14422 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
14423 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
14425 memset(&transformdata, 0, sizeof(transformdata));
14426 transformdata.dwSize = sizeof(transformdata);
14427 transformdata.lpIn = position_tests;
14428 transformdata.dwInSize = sizeof(position_tests[0]);
14429 transformdata.lpOut = out;
14430 transformdata.dwOutSize = sizeof(out[0]);
14431 transformdata.lpHOut = NULL;
14433 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
14434 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
14435 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14436 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
14438 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
14440 static const struct vec4 cmp[] =
14442 {128.0f, 128.0f, 0.0f, 1.0f}, {129.0f, 127.0f, 1.0f, 1.0f}, {127.0f, 129.0f, -1.0f, 1.0f},
14443 {128.5f, 127.5f, 0.5f, 1.0f}, {127.5f, 128.5f, -0.5f, 1.0f}, {127.5f, 128.5f, 0.0f, 1.0f}
14446 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
14447 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
14448 out[i].x, out[i].y, out[i].z, out[i].w);
14449 ok(out[i].v1 == position_tests[i].v1 && out[i].v2 == position_tests[i].v2
14450 && out[i].v3 == position_tests[i].v3 && out[i].v4 == position_tests[i].v4,
14451 "Vertex %u payload is %u %u %u %u.\n", i, out[i].v1, out[i].v2, out[i].v3, out[i].v4);
14452 ok(out[i].unused3 == 0xdeadbeef && out[i].unused4 == 0xcafecafe,
14453 "Vertex %u unused data is %#x, %#x.\n", i, out[i].unused3, out[i].unused4);
14456 vp_data = vp_template;
14457 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
14458 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
14459 offscreen = 0xdeadbeef;
14460 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
14461 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
14462 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14463 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
14465 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
14467 static const struct vec4 cmp[] =
14469 {128.0f, 128.0f, 0.0f, 1.0f}, {133.0f, 123.0f, 1.0f, 1.0f}, {123.0f, 133.0f, -1.0f, 1.0f},
14470 {130.5f, 125.5f, 0.5f, 1.0f}, {125.5f, 130.5f, -0.5f, 1.0f}, {125.5f, 130.5f, 0.0f, 1.0f}
14472 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
14473 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
14474 out[i].x, out[i].y, out[i].z, out[i].w);
14477 vp_data.dwX = 10;
14478 vp_data.dwY = 20;
14479 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
14480 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
14481 offscreen = 0xdeadbeef;
14482 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
14483 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
14484 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14485 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
14486 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
14488 static const struct vec4 cmp[] =
14490 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, {133.0f, 153.0f, -1.0f, 1.0f},
14491 {140.5f, 145.5f, 0.5f, 1.0f}, {135.5f, 150.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
14493 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
14494 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
14495 out[i].x, out[i].y, out[i].z, out[i].w);
14498 transformdata.lpHOut = out_h;
14499 offscreen = 0xdeadbeef;
14500 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
14501 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14502 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14503 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
14504 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
14506 static const D3DHVERTEX cmp_h[] =
14508 {0, { 0.0f}, { 0.0f}, { 0.0f}}, {0, { 1.0f}, { 1.0f}, {1.0f}},
14509 {D3DCLIP_FRONT, {-1.0f}, {-1.0f}, {-1.0f}}, {0, { 0.5f}, { 0.5f}, {0.5f}},
14510 {D3DCLIP_FRONT, {-0.5f}, {-0.5f}, {-0.5f}}, {0, {-0.5f}, {-0.5f}, {0.0f}}
14512 ok(compare_float(U1(cmp_h[i]).hx, U1(out_h[i]).hx, 4096)
14513 && compare_float(U2(cmp_h[i]).hy, U2(out_h[i]).hy, 4096)
14514 && compare_float(U3(cmp_h[i]).hz, U3(out_h[i]).hz, 4096)
14515 && cmp_h[i].dwFlags == out_h[i].dwFlags,
14516 "HVertex %u differs. Got %#lx %.8e %.8e %.8e.\n", i,
14517 out_h[i].dwFlags, U1(out_h[i]).hx, U2(out_h[i]).hy, U3(out_h[i]).hz);
14519 /* No scheme has been found behind those return values. It seems to be
14520 * whatever data windows has when throwing the vertex away. Modify the
14521 * input test vertices to test this more. Depending on the input data
14522 * it can happen that the z coord gets written into y, or similar things. */
14523 if (0)
14525 static const struct vec4 cmp[] =
14527 {138.0f, 148.0f, 0.0f, 1.0f}, {143.0f, 143.0f, 1.0f, 1.0f}, { -1.0f, -1.0f, 0.5f, 1.0f},
14528 {140.5f, 145.5f, 0.5f, 1.0f}, { -0.5f, -0.5f, -0.5f, 1.0f}, {135.5f, 150.5f, 0.0f, 1.0f}
14530 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
14531 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
14532 out[i].x, out[i].y, out[i].z, out[i].w);
14536 transformdata.lpIn = cliptest;
14537 transformdata.dwInSize = sizeof(cliptest[0]);
14538 offscreen = 0xdeadbeef;
14539 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
14540 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14541 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14542 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
14543 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
14545 static const DWORD flags[] =
14548 D3DCLIP_RIGHT | D3DCLIP_BACK | D3DCLIP_TOP,
14550 D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
14552 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#lx.\n", i, out_h[i].dwFlags);
14555 vp_data = vp_template;
14556 vp_data.dwWidth = 10;
14557 vp_data.dwHeight = 480;
14558 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
14559 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
14560 offscreen = 0xdeadbeef;
14561 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
14562 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14563 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14564 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
14565 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
14567 static const DWORD flags[] =
14569 D3DCLIP_RIGHT,
14570 D3DCLIP_RIGHT | D3DCLIP_BACK,
14571 D3DCLIP_LEFT,
14572 D3DCLIP_LEFT | D3DCLIP_FRONT,
14574 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#lx.\n", i, out_h[i].dwFlags);
14577 vp_data = vp_template;
14578 vp_data.dwWidth = 256;
14579 vp_data.dwHeight = 256;
14580 vp_data.dvScaleX = 1;
14581 vp_data.dvScaleY = 1;
14582 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
14583 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
14584 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(cliptest),
14585 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14586 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14587 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
14588 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
14590 static const DWORD flags[] =
14593 D3DCLIP_BACK,
14595 D3DCLIP_FRONT,
14597 ok(flags[i] == out_h[i].dwFlags, "Cliptest %u returned %#lx.\n", i, out_h[i].dwFlags);
14600 /* Finally try to figure out how the DWORD dwOffscreen works.
14601 * It is a logical AND of the vertices' dwFlags members. */
14602 vp_data = vp_template;
14603 vp_data.dwWidth = 5;
14604 vp_data.dwHeight = 5;
14605 vp_data.dvScaleX = 10000.0f;
14606 vp_data.dvScaleY = 10000.0f;
14607 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
14608 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
14609 transformdata.lpIn = cliptest;
14610 offscreen = 0xdeadbeef;
14611 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
14612 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
14613 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14614 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
14616 offscreen = 0xdeadbeef;
14617 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
14618 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14619 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14620 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %#lx.\n", offscreen);
14621 offscreen = 0xdeadbeef;
14622 hr = IDirect3DViewport2_TransformVertices(viewport, 2,
14623 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14624 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14625 ok(offscreen == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %#lx.\n", offscreen);
14626 hr = IDirect3DViewport2_TransformVertices(viewport, 3,
14627 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14628 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14629 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
14631 transformdata.lpIn = cliptest + 1;
14632 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
14633 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14634 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14635 ok(offscreen == (D3DCLIP_BACK | D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %#lx.\n", offscreen);
14637 transformdata.lpIn = cliptest + 2;
14638 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
14639 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14640 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14641 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %#lx.\n", offscreen);
14642 offscreen = 0xdeadbeef;
14643 hr = IDirect3DViewport2_TransformVertices(viewport, 2,
14644 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14645 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14646 ok(offscreen == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %#lx.\n", offscreen);
14648 transformdata.lpIn = cliptest + 3;
14649 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
14650 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14651 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14652 ok(offscreen == (D3DCLIP_FRONT | D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %#lx.\n", offscreen);
14654 transformdata.lpIn = offscreentest;
14655 transformdata.dwInSize = sizeof(offscreentest[0]);
14656 vp_data = vp_template;
14657 vp_data.dwWidth = 257;
14658 vp_data.dwHeight = 257;
14659 vp_data.dvScaleX = 1.0f;
14660 vp_data.dvScaleY = 1.0f;
14661 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
14662 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
14663 offscreen = 0xdeadbeef;
14664 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
14665 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14666 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14667 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
14669 vp_data.dwWidth = 256;
14670 vp_data.dwHeight = 256;
14671 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
14672 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
14673 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
14674 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14675 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14676 ok(offscreen == D3DCLIP_RIGHT, "Offscreen is %#lx.\n", offscreen);
14678 /* Test the effect of Matrices.
14680 * Basically the x coordinate ends up as ((x + 1) * 2 + 0) * 5 and
14681 * y as ((y + 0) * 2 + 1) * 5. The 5 comes from dvScaleX/Y, 2 from
14682 * the view matrix and the +1's from the world and projection matrix. */
14683 vp_data.dwX = 0;
14684 vp_data.dwY = 0;
14685 vp_data.dwWidth = 256;
14686 vp_data.dwHeight = 256;
14687 vp_data.dvScaleX = 5.0f;
14688 vp_data.dvScaleY = 5.0f;
14689 vp_data.dvMinZ = 0.0f;
14690 vp_data.dvMaxZ = 1.0f;
14691 hr = IDirect3DViewport2_SetViewport(viewport, &vp_data);
14692 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
14694 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat_translate1);
14695 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
14696 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat_scale);
14697 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
14698 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat_translate2);
14699 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
14701 transformdata.lpIn = position_tests;
14702 transformdata.dwInSize = sizeof(position_tests[0]);
14703 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
14704 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
14705 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14707 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
14709 static const struct vec4 cmp[] =
14711 {138.0f, 123.0f, 0.0f, 1.0f}, {148.0f, 113.0f, 2.0f, 1.0f}, {128.0f, 133.0f, -2.0f, 1.0f},
14712 {143.0f, 118.0f, 1.0f, 1.0f}, {133.0f, 128.0f, -1.0f, 1.0f}, {133.0f, 128.0f, 0.0f, 1.0f}
14715 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
14716 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
14717 out[i].x, out[i].y, out[i].z, out[i].w);
14720 /* Invalid flags. */
14721 offscreen = 0xdeadbeef;
14722 hr = IDirect3DViewport2_TransformVertices(viewport, ARRAY_SIZE(position_tests),
14723 &transformdata, 0, &offscreen);
14724 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
14725 ok(offscreen == 0xdeadbeef, "Offscreen is %#lx.\n", offscreen);
14727 /* NULL transform data. */
14728 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
14729 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
14730 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
14731 ok(offscreen == 0xdeadbeef, "Offscreen is %#lx.\n", offscreen);
14732 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
14733 NULL, D3DTRANSFORM_UNCLIPPED, &offscreen);
14734 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
14735 ok(offscreen == 0xdeadbeef, "Offscreen is %#lx.\n", offscreen);
14737 /* NULL transform data and NULL dwOffscreen.
14739 * Valid transform data + NULL dwOffscreen -> crash. */
14740 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
14741 NULL, D3DTRANSFORM_UNCLIPPED, NULL);
14742 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
14744 /* No vertices. */
14745 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
14746 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
14747 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14748 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
14749 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
14750 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14751 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14752 ok(offscreen == ~0u, "Offscreen is %#lx.\n", offscreen);
14754 /* Invalid sizes. */
14755 offscreen = 0xdeadbeef;
14756 transformdata.dwSize = sizeof(transformdata) - 1;
14757 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
14758 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
14759 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
14760 ok(offscreen == 0xdeadbeef, "Offscreen is %#lx.\n", offscreen);
14761 transformdata.dwSize = sizeof(transformdata) + 1;
14762 hr = IDirect3DViewport2_TransformVertices(viewport, 1,
14763 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
14764 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
14765 ok(offscreen == 0xdeadbeef, "Offscreen is %#lx.\n", offscreen);
14767 /* NULL lpIn or lpOut -> crash, except when transforming 0 vertices. */
14768 transformdata.dwSize = sizeof(transformdata);
14769 transformdata.lpIn = NULL;
14770 transformdata.lpOut = NULL;
14771 offscreen = 0xdeadbeef;
14772 hr = IDirect3DViewport2_TransformVertices(viewport, 0,
14773 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14774 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14775 ok(offscreen == ~0u, "Offscreen is %#lx.\n", offscreen);
14777 /* Test how vertices are transformed during draws. */
14778 vp_data.dwX = 20;
14779 vp_data.dwY = 20;
14780 vp_data.dwWidth = 200;
14781 vp_data.dwHeight = 400;
14782 vp_data.dvScaleX = 20.0f;
14783 vp_data.dvScaleY = 50.0f;
14784 vp_data.dvMinZ = 0.0f;
14785 vp_data.dvMaxZ = 1.0f;
14786 hr = IDirect3DViewport3_SetViewport(viewport, &vp_data);
14787 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
14788 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
14789 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#lx.\n", hr);
14791 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
14792 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
14794 hr = IDirect3DDevice3_BeginScene(device);
14795 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
14796 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14797 quad, 4, 0);
14798 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14799 hr = IDirect3DDevice3_EndScene(device);
14800 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
14802 color = get_surface_color(rt, 128, 143);
14803 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
14804 color = get_surface_color(rt, 132, 143);
14805 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
14806 color = get_surface_color(rt, 128, 147);
14807 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
14808 color = get_surface_color(rt, 132, 147);
14809 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
14811 color = get_surface_color(rt, 177, 217);
14812 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
14813 color = get_surface_color(rt, 181, 217);
14814 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
14815 color = get_surface_color(rt, 177, 221);
14816 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
14817 color = get_surface_color(rt, 181, 221);
14818 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
14820 /* Test D3DVIEWPORT2 behavior. */
14821 vp2_data.dwSize = sizeof(vp2_data);
14822 vp2_data.dwX = 20;
14823 vp2_data.dwY = 20;
14824 vp2_data.dwWidth = 200;
14825 vp2_data.dwHeight = 400;
14826 vp2_data.dvClipX = -0.5f;
14827 vp2_data.dvClipY = 4.0f;
14828 vp2_data.dvClipWidth = 5.0f;
14829 vp2_data.dvClipHeight = 10.0f;
14830 vp2_data.dvMinZ = 0.0f;
14831 vp2_data.dvMaxZ = 2.0f;
14832 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2_data);
14833 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#lx.\n", hr);
14834 transformdata.lpIn = position_tests;
14835 transformdata.lpOut = out;
14836 hr = IDirect3DViewport3_TransformVertices(viewport, ARRAY_SIZE(position_tests),
14837 &transformdata, D3DTRANSFORM_UNCLIPPED, &offscreen);
14838 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14839 for (i = 0; i < ARRAY_SIZE(position_tests); ++i)
14841 static const struct vec4 cmp[] =
14843 {120.0f, 140.0f, 0.0f, 1.0f}, {200.0f, 60.0f, 1.0f, 1.0f}, {40.0f, 220.0f, -1.0f, 1.0f},
14844 {160.0f, 100.0f, 0.5f, 1.0f}, { 80.0f, 180.0f, -0.5f, 1.0f}, {80.0f, 180.0f, 0.0f, 1.0f}
14847 ok(compare_vec4(&cmp[i], out[i].x, out[i].y, out[i].z, out[i].w, 4096),
14848 "Vertex %u differs. Got %.8e %.8e %.8e %.8e.\n", i,
14849 out[i].x, out[i].y, out[i].z, out[i].w);
14852 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x0000ff00, 0.0f, 0);
14853 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#lx.\n", hr);
14855 hr = IDirect3DDevice3_BeginScene(device);
14856 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
14857 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14858 quad, 4, 0);
14859 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
14860 hr = IDirect3DDevice3_EndScene(device);
14861 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
14863 color = get_surface_color(rt, 58, 118);
14864 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
14865 color = get_surface_color(rt, 62, 118);
14866 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
14867 color = get_surface_color(rt, 58, 122);
14868 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
14869 color = get_surface_color(rt, 62, 122);
14870 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
14872 color = get_surface_color(rt, 157, 177);
14873 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
14874 color = get_surface_color(rt, 161, 177);
14875 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
14876 color = get_surface_color(rt, 157, 181);
14877 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
14878 color = get_surface_color(rt, 161, 181);
14879 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
14881 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat_identity);
14882 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
14883 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat_identity);
14884 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
14885 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat_transform3);
14886 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
14888 vp2_data.dwX = 0.0;
14889 vp2_data.dwY = 0.0;
14890 vp2_data.dwWidth = 1;
14891 vp2_data.dwHeight = 1;
14892 vp2_data.dvClipX = -12.8f;
14893 vp2_data.dvClipY = 12.8f + mat_transform3._42 / mat_transform3._44;
14894 vp2_data.dvClipWidth = 25.6f;
14895 vp2_data.dvClipHeight = 25.6f;
14896 vp2_data.dvMinZ = 0.0f;
14897 vp2_data.dvMaxZ = 0.5f;
14898 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2_data);
14899 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#lx.\n", hr);
14900 transformdata.lpIn = cliptest;
14901 transformdata.dwInSize = sizeof(cliptest[0]);
14902 offscreen = 0xdeadbeef;
14903 hr = IDirect3DViewport3_TransformVertices(viewport, ARRAY_SIZE(cliptest),
14904 &transformdata, D3DTRANSFORM_CLIPPED, &offscreen);
14905 ok(SUCCEEDED(hr), "Failed to transform vertices, hr %#lx.\n", hr);
14906 ok(!offscreen, "Offscreen is %#lx.\n", offscreen);
14907 for (i = 0; i < ARRAY_SIZE(cliptest); ++i)
14909 static const D3DHVERTEX cmp_h[] =
14911 {0, { 25.59f}, { 44.79f}, { 1.0f }},
14912 {D3DCLIP_RIGHT | D3DCLIP_TOP | D3DCLIP_BACK, { 25.61f}, { 44.81f}, { 1.01f}},
14913 {0, {-25.59f}, {-6.39f }, { 0.0f }},
14914 {D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,{-25.61f}, {-6.41f }, {-0.01f}},
14916 ok(compare_float(U1(cmp_h[i]).hx, U1(out_h[i]).hx, 4096)
14917 && compare_float(U2(cmp_h[i]).hy, U2(out_h[i]).hy, 4096)
14918 && compare_float(U3(cmp_h[i]).hz, U3(out_h[i]).hz, 4096)
14919 && cmp_h[i].dwFlags == out_h[i].dwFlags,
14920 "HVertex %u differs. Got %#lx %.8e %.8e %.8e.\n", i,
14921 out_h[i].dwFlags, U1(out_h[i]).hx, U2(out_h[i]).hy, U3(out_h[i]).hz);
14924 destroy_viewport(device, viewport);
14925 IDirectDrawSurface4_Release(rt);
14926 refcount = IDirect3DDevice3_Release(device);
14927 ok(!refcount, "Device has %lu references left.\n", refcount);
14928 DestroyWindow(window);
14931 static void test_display_mode_surface_pixel_format(void)
14933 unsigned int width, height, bpp;
14934 IDirectDrawSurface4 *surface;
14935 DDSURFACEDESC2 surface_desc;
14936 IDirectDraw4 *ddraw;
14937 ULONG refcount;
14938 HWND window;
14939 HRESULT hr;
14941 if (!(ddraw = create_ddraw()))
14943 skip("Failed to create ddraw.\n");
14944 return;
14947 surface_desc.dwSize = sizeof(surface_desc);
14948 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
14949 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#lx.\n", hr);
14950 width = surface_desc.dwWidth;
14951 height = surface_desc.dwHeight;
14953 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
14954 0, 0, width, height, NULL, NULL, NULL, NULL);
14955 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
14956 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
14958 bpp = 0;
14959 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 16, 0, 0)))
14960 bpp = 16;
14961 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 24, 0, 0)))
14962 bpp = 24;
14963 if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
14964 bpp = 32;
14965 ok(bpp, "Set display mode failed.\n");
14967 surface_desc.dwSize = sizeof(surface_desc);
14968 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
14969 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#lx.\n", hr);
14970 ok(surface_desc.dwWidth == width, "Got width %lu, expected %u.\n", surface_desc.dwWidth, width);
14971 ok(surface_desc.dwHeight == height, "Got height %lu, expected %u.\n", surface_desc.dwHeight, height);
14972 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %lu, expected %u.\n",
14973 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
14975 memset(&surface_desc, 0, sizeof(surface_desc));
14976 surface_desc.dwSize = sizeof(surface_desc);
14977 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
14978 U5(surface_desc).dwBackBufferCount = 1;
14979 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
14980 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14981 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
14982 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
14983 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
14984 ok(surface_desc.dwWidth == width, "Got width %lu, expected %u.\n", surface_desc.dwWidth, width);
14985 ok(surface_desc.dwHeight == height, "Got height %lu, expected %u.\n", surface_desc.dwHeight, height);
14986 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#lx.\n",
14987 U4(surface_desc).ddpfPixelFormat.dwFlags);
14988 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %lu, expected %u.\n",
14989 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
14990 IDirectDrawSurface4_Release(surface);
14992 memset(&surface_desc, 0, sizeof(surface_desc));
14993 surface_desc.dwSize = sizeof(surface_desc);
14994 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
14995 surface_desc.dwWidth = width;
14996 surface_desc.dwHeight = height;
14997 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
14998 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14999 ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
15000 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
15001 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
15002 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#lx.\n",
15003 U4(surface_desc).ddpfPixelFormat.dwFlags);
15004 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %lu, expected %u.\n",
15005 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
15006 IDirectDrawSurface4_Release(surface);
15008 refcount = IDirectDraw4_Release(ddraw);
15009 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
15010 DestroyWindow(window);
15013 static void test_surface_desc_size(void)
15015 union
15017 DWORD dwSize;
15018 DDSURFACEDESC desc1;
15019 DDSURFACEDESC2 desc2;
15020 BYTE blob[1024];
15021 } desc;
15022 IDirectDrawSurface4 *surface4;
15023 IDirectDrawSurface3 *surface3;
15024 IDirectDrawSurface *surface;
15025 DDSURFACEDESC2 surface_desc;
15026 HRESULT expected_hr, hr;
15027 IDirectDraw4 *ddraw;
15028 unsigned int i, j;
15029 ULONG refcount;
15031 static const struct
15033 unsigned int caps;
15034 const char *name;
15036 surface_caps[] =
15038 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
15039 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
15040 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
15042 static const unsigned int desc_sizes[] =
15044 sizeof(DDSURFACEDESC),
15045 sizeof(DDSURFACEDESC2),
15046 sizeof(DDSURFACEDESC) + 1,
15047 sizeof(DDSURFACEDESC2) + 1,
15048 2 * sizeof(DDSURFACEDESC),
15049 2 * sizeof(DDSURFACEDESC2),
15050 sizeof(DDSURFACEDESC) - 1,
15051 sizeof(DDSURFACEDESC2) - 1,
15052 sizeof(DDSURFACEDESC) / 2,
15053 sizeof(DDSURFACEDESC2) / 2,
15057 sizeof(desc) / 2,
15058 sizeof(desc) - 100,
15061 if (!(ddraw = create_ddraw()))
15063 skip("Failed to create ddraw.\n");
15064 return;
15066 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
15067 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
15069 for (i = 0; i < ARRAY_SIZE(surface_caps); ++i)
15071 memset(&surface_desc, 0, sizeof(surface_desc));
15072 surface_desc.dwSize = sizeof(surface_desc);
15073 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
15074 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
15075 surface_desc.dwHeight = 128;
15076 surface_desc.dwWidth = 128;
15077 if (FAILED(IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface4, NULL)))
15079 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
15080 continue;
15082 hr = IDirectDrawSurface_QueryInterface(surface4, &IID_IDirectDrawSurface, (void **)&surface);
15083 ok(hr == DD_OK, "Failed to query IDirectDrawSurface, hr %#lx, type %s.\n", hr, surface_caps[i].name);
15084 hr = IDirectDrawSurface_QueryInterface(surface4, &IID_IDirectDrawSurface3, (void **)&surface3);
15085 ok(hr == DD_OK, "Failed to query IDirectDrawSurface3, hr %#lx, type %s.\n", hr, surface_caps[i].name);
15087 /* GetSurfaceDesc() */
15088 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
15090 memset(&desc, 0, sizeof(desc));
15091 desc.dwSize = desc_sizes[j];
15092 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
15093 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
15094 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
15095 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
15097 memset(&desc, 0, sizeof(desc));
15098 desc.dwSize = desc_sizes[j];
15099 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
15100 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &desc.desc1);
15101 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
15102 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
15104 memset(&desc, 0, sizeof(desc));
15105 desc.dwSize = desc_sizes[j];
15106 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
15107 hr = IDirectDrawSurface4_GetSurfaceDesc(surface4, &desc.desc2);
15108 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
15109 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
15112 /* Lock() */
15113 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
15115 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
15116 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
15117 DWORD expected_texture_stage;
15119 memset(&desc, 0, sizeof(desc));
15120 desc.dwSize = desc_sizes[j];
15121 desc.desc2.dwTextureStage = 0xdeadbeef;
15122 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
15123 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
15124 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
15125 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
15126 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
15127 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %lu, type %s.\n",
15128 desc_sizes[j], desc.dwSize, surface_caps[i].name);
15129 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, size %u, type %s.\n",
15130 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
15131 if (SUCCEEDED(hr))
15133 ok(desc.desc1.dwWidth == 128, "Got unexpected width %lu, size %u, type %s.\n",
15134 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
15135 ok(desc.desc1.dwHeight == 128, "Got unexpected height %lu, size %u, type %s.\n",
15136 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
15137 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
15138 todo_wine_if(!expected_texture_stage)
15139 ok(desc.desc2.dwTextureStage == expected_texture_stage,
15140 "Got unexpected texture stage %#lx, size %u, type %s.\n",
15141 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
15142 IDirectDrawSurface_Unlock(surface, NULL);
15145 memset(&desc, 0, sizeof(desc));
15146 desc.dwSize = desc_sizes[j];
15147 desc.desc2.dwTextureStage = 0xdeadbeef;
15148 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
15149 hr = IDirectDrawSurface3_Lock(surface3, NULL, &desc.desc1, 0, 0);
15150 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
15151 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
15152 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
15153 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %lu, type %s.\n",
15154 desc_sizes[j], desc.dwSize, surface_caps[i].name);
15155 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, size %u, type %s.\n",
15156 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
15157 if (SUCCEEDED(hr))
15159 ok(desc.desc1.dwWidth == 128, "Got unexpected width %lu, size %u, type %s.\n",
15160 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
15161 ok(desc.desc1.dwHeight == 128, "Got unexpected height %lu, size %u, type %s.\n",
15162 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
15163 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
15164 todo_wine_if(!expected_texture_stage)
15165 ok(desc.desc2.dwTextureStage == expected_texture_stage,
15166 "Got unexpected texture stage %#lx, size %u, type %s.\n",
15167 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
15168 IDirectDrawSurface3_Unlock(surface3, NULL);
15171 memset(&desc, 0, sizeof(desc));
15172 desc.dwSize = desc_sizes[j];
15173 desc.desc2.dwTextureStage = 0xdeadbeef;
15174 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
15175 hr = IDirectDrawSurface4_Lock(surface4, NULL, &desc.desc2, 0, 0);
15176 expected_hr = valid_size ? DD_OK : DDERR_INVALIDPARAMS;
15177 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u, type %s.\n",
15178 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
15179 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %lu, type %s.\n",
15180 desc_sizes[j], desc.dwSize, surface_caps[i].name);
15181 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, size %u, type %s.\n",
15182 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
15183 if (SUCCEEDED(hr))
15185 ok(desc.desc2.dwWidth == 128, "Got unexpected width %lu, size %u, type %s.\n",
15186 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
15187 ok(desc.desc2.dwHeight == 128, "Got unexpected height %lu, size %u, type %s.\n",
15188 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
15189 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
15190 ok(desc.desc2.dwTextureStage == expected_texture_stage,
15191 "Got unexpected texture stage %#lx, size %u, type %s.\n",
15192 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
15193 IDirectDrawSurface4_Unlock(surface4, NULL);
15197 IDirectDrawSurface4_Release(surface4);
15198 IDirectDrawSurface3_Release(surface3);
15199 IDirectDrawSurface_Release(surface);
15202 /* GetDisplayMode() */
15203 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
15205 memset(&desc, 0xcc, sizeof(desc));
15206 desc.dwSize = desc_sizes[j];
15207 expected_hr = (desc.dwSize == sizeof(DDSURFACEDESC) || desc.dwSize == sizeof(DDSURFACEDESC2))
15208 ? DD_OK : DDERR_INVALIDPARAMS;
15209 hr = IDirectDraw4_GetDisplayMode(ddraw, &desc.desc2);
15210 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, size %u.\n", hr, expected_hr, desc_sizes[j]);
15211 if (SUCCEEDED(hr))
15213 ok(desc.dwSize == sizeof(DDSURFACEDESC2), "Wrong size %lu for %u.\n", desc.dwSize, desc_sizes[j]);
15214 ok(desc.blob[desc_sizes[j]] == 0xcc, "Overflow for size %u.\n", desc_sizes[j]);
15215 ok(desc.blob[desc_sizes[j] - 1] != 0xcc, "Struct not cleared for size %u.\n", desc_sizes[j]);
15219 refcount = IDirectDraw4_Release(ddraw);
15220 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
15223 static void test_get_surface_from_dc(void)
15225 IDirectDrawSurface *surface1, *tmp;
15226 IDirectDrawSurface4 *surface;
15227 DDSURFACEDESC2 surface_desc;
15228 IDirectDraw4 *ddraw;
15229 HDC dc, device_dc;
15230 ULONG refcount;
15231 HWND window;
15232 HRESULT hr;
15233 DWORD ret;
15235 window = create_window();
15236 ddraw = create_ddraw();
15237 ok(!!ddraw, "Failed to create a ddraw object.\n");
15238 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
15239 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
15241 memset(&surface_desc, 0, sizeof(surface_desc));
15242 surface_desc.dwSize = sizeof(surface_desc);
15243 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
15244 surface_desc.dwWidth = 64;
15245 surface_desc.dwHeight = 64;
15246 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
15248 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
15249 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
15250 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirectDrawSurface, (void **)&surface1);
15251 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#lx.\n", hr);
15253 refcount = get_refcount((IUnknown *)surface1);
15254 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
15255 refcount = get_refcount((IUnknown *)surface);
15256 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
15258 hr = IDirectDrawSurface4_GetDC(surface, &dc);
15259 ok(SUCCEEDED(hr), "Failed to get DC, hr %#lx.\n", hr);
15261 tmp = (void *)0xdeadbeef;
15262 device_dc = (void *)0xdeadbeef;
15263 hr = GetSurfaceFromDC(NULL, &tmp, &device_dc);
15264 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
15265 ok(!tmp, "Got unexpected surface %p.\n", tmp);
15266 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
15268 device_dc = (void *)0xdeadbeef;
15269 hr = GetSurfaceFromDC(dc, NULL, &device_dc);
15270 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
15271 ok(device_dc == (void *)0xdeadbeef, "Got unexpected device_dc %p.\n", device_dc);
15273 tmp = (void *)0xdeadbeef;
15274 hr = GetSurfaceFromDC(dc, &tmp, NULL);
15275 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
15276 ok(!tmp, "Got unexpected surface %p.\n", tmp);
15278 hr = GetSurfaceFromDC(dc, &tmp, &device_dc);
15279 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#lx.\n", hr);
15280 ok(tmp == surface1, "Got unexpected surface %p, expected %p.\n", tmp, surface1);
15281 IDirectDrawSurface_Release(tmp);
15283 ret = GetObjectType(device_dc);
15284 todo_wine ok(ret == OBJ_DC, "Got unexpected object type %#lx.\n", ret);
15285 ret = GetDeviceCaps(device_dc, TECHNOLOGY);
15286 todo_wine ok(ret == DT_RASDISPLAY, "Got unexpected technology %#lx.\n", ret);
15288 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, dc, NULL);
15289 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
15291 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, dc, (IDirectDrawSurface4 **)&tmp);
15292 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#lx.\n", hr);
15293 ok(tmp == surface1, "Got unexpected surface %p, expected %p.\n", tmp, surface1);
15295 refcount = get_refcount((IUnknown *)surface1);
15296 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
15297 refcount = get_refcount((IUnknown *)surface);
15298 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
15300 hr = IDirectDrawSurface4_ReleaseDC(surface, dc);
15301 ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#lx.\n", hr);
15303 IDirectDrawSurface_Release(tmp);
15305 dc = CreateCompatibleDC(NULL);
15306 ok(!!dc, "CreateCompatibleDC failed.\n");
15308 tmp = (void *)0xdeadbeef;
15309 device_dc = (void *)0xdeadbeef;
15310 hr = GetSurfaceFromDC(dc, &tmp, &device_dc);
15311 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
15312 ok(!tmp, "Got unexpected surface %p.\n", tmp);
15313 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
15315 tmp = (void *)0xdeadbeef;
15316 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, dc, (IDirectDrawSurface4 **)&tmp);
15317 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
15318 ok(!tmp, "Got unexpected surface %p.\n", tmp);
15320 ok(DeleteDC(dc), "DeleteDC failed.\n");
15322 tmp = (void *)0xdeadbeef;
15323 hr = IDirectDraw4_GetSurfaceFromDC(ddraw, NULL, (IDirectDrawSurface4 **)&tmp);
15324 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
15325 ok(!tmp, "Got unexpected surface %p.\n", tmp);
15327 IDirectDrawSurface4_Release(surface);
15328 IDirectDrawSurface_Release(surface1);
15329 IDirectDraw4_Release(ddraw);
15330 DestroyWindow(window);
15333 static void test_ck_operation(void)
15335 IDirectDrawSurface4 *src, *dst;
15336 IDirectDrawSurface *src1, *dst1;
15337 DDSURFACEDESC2 surface_desc;
15338 unsigned int i, *color;
15339 IDirectDraw4 *ddraw;
15340 ULONG refcount;
15341 HWND window;
15342 HRESULT hr;
15343 DDCOLORKEY ckey;
15344 DDBLTFX fx;
15346 window = create_window();
15347 ddraw = create_ddraw();
15348 ok(!!ddraw, "Failed to create a ddraw object.\n");
15349 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
15350 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
15352 memset(&surface_desc, 0, sizeof(surface_desc));
15353 surface_desc.dwSize = sizeof(surface_desc);
15354 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
15355 surface_desc.dwWidth = 4;
15356 surface_desc.dwHeight = 1;
15357 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
15358 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
15359 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
15360 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
15361 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
15362 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
15363 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
15364 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
15366 surface_desc.dwFlags |= DDSD_CKSRCBLT;
15367 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
15368 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff;
15369 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
15370 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
15372 hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15373 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
15374 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
15375 color = surface_desc.lpSurface;
15376 color[0] = 0x77010203;
15377 color[1] = 0x00010203;
15378 color[2] = 0x77ff00ff;
15379 color[3] = 0x00ff00ff;
15380 hr = IDirectDrawSurface4_Unlock(src, NULL);
15381 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
15383 for (i = 0; i < 2; ++i)
15385 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15386 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
15387 color = surface_desc.lpSurface;
15388 color[0] = 0xcccccccc;
15389 color[1] = 0xcccccccc;
15390 color[2] = 0xcccccccc;
15391 color[3] = 0xcccccccc;
15392 hr = IDirectDrawSurface4_Unlock(dst, NULL);
15393 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
15395 if (i)
15397 hr = IDirectDrawSurface4_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY);
15398 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
15400 else
15402 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL);
15403 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
15406 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL);
15407 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
15408 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
15409 color = surface_desc.lpSurface;
15410 /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
15411 * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for
15412 * color keying, but do not copy it into the destination surface. Nvidia neither uses it for
15413 * color keying nor copies it. */
15414 ok((color[0] == 0x77010203 && color[1] == 0x00010203
15415 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */
15416 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
15417 && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */
15418 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
15419 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */
15420 || broken(color[0] == 0xff010203 && color[1] == 0xff010203
15421 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */,
15422 "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n",
15423 color[0], color[1], color[2], color[3], i);
15424 hr = IDirectDrawSurface4_Unlock(dst, NULL);
15425 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
15428 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
15429 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
15430 ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff,
15431 "Got unexpected color key low=%08lx high=%08lx.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
15433 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
15434 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
15435 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
15437 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
15438 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
15439 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
15440 ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00,
15441 "Got unexpected color key low=%08lx high=%08lx.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
15443 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
15444 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
15445 hr = IDirectDrawSurface4_GetSurfaceDesc(src, &surface_desc);
15446 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
15447 ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00
15448 && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00,
15449 "Got unexpected color key low=%08lx high=%08lx.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
15450 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
15452 /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
15453 ckey.dwColorSpaceLowValue = 0x000000ff;
15454 ckey.dwColorSpaceHighValue = 0x00000000;
15455 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
15456 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
15458 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
15459 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
15460 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
15461 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
15462 "Got unexpected color key low=%08lx high=%08lx.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
15464 ckey.dwColorSpaceLowValue = 0x000000ff;
15465 ckey.dwColorSpaceHighValue = 0x00000001;
15466 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
15467 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
15469 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
15470 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
15471 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
15472 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
15473 "Got unexpected color key low=%08lx high=%08lx.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
15475 ckey.dwColorSpaceLowValue = 0x000000fe;
15476 ckey.dwColorSpaceHighValue = 0x000000fd;
15477 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
15478 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
15480 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
15481 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
15482 ok(SUCCEEDED(hr), "Failed to get color key, hr %#lx.\n", hr);
15483 ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe,
15484 "Got unexpected color key low=%08lx high=%08lx.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
15486 IDirectDrawSurface4_Release(src);
15487 IDirectDrawSurface4_Release(dst);
15489 /* Test source and destination keys and where they are read from. Use a surface with alpha
15490 * to avoid driver-dependent content in the X channel. */
15491 memset(&surface_desc, 0, sizeof(surface_desc));
15492 surface_desc.dwSize = sizeof(surface_desc);
15493 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
15494 surface_desc.dwWidth = 6;
15495 surface_desc.dwHeight = 1;
15496 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
15497 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
15498 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
15499 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
15500 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
15501 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
15502 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
15503 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
15504 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
15505 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
15506 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
15508 ckey.dwColorSpaceLowValue = 0x0000ff00;
15509 ckey.dwColorSpaceHighValue = 0x0000ff00;
15510 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
15511 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
15512 ckey.dwColorSpaceLowValue = 0x00ff0000;
15513 ckey.dwColorSpaceHighValue = 0x00ff0000;
15514 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_DESTBLT, &ckey);
15515 ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#lx.\n", hr);
15516 if (FAILED(hr))
15518 /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */
15519 skip("Failed to set destination color key, skipping related tests.\n");
15520 goto done;
15523 ckey.dwColorSpaceLowValue = 0x000000ff;
15524 ckey.dwColorSpaceHighValue = 0x000000ff;
15525 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
15526 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
15527 ckey.dwColorSpaceLowValue = 0x000000aa;
15528 ckey.dwColorSpaceHighValue = 0x000000aa;
15529 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_DESTBLT, &ckey);
15530 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
15532 memset(&fx, 0, sizeof(fx));
15533 fx.dwSize = sizeof(fx);
15534 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000;
15535 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000;
15536 fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100;
15537 fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100;
15539 hr = IDirectDrawSurface4_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15540 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
15541 color = surface_desc.lpSurface;
15542 color[0] = 0x000000ff; /* Applies to src blt key in src surface. */
15543 color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */
15544 color[2] = 0x00ff0000; /* Dst color key in dst surface. */
15545 color[3] = 0x0000ff00; /* Src color key in dst surface. */
15546 color[4] = 0x00001100; /* Src color key in ddbltfx. */
15547 color[5] = 0x00110000; /* Dst color key in ddbltfx. */
15548 hr = IDirectDrawSurface4_Unlock(src, NULL);
15549 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
15551 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15552 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
15553 color = surface_desc.lpSurface;
15554 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
15555 hr = IDirectDrawSurface4_Unlock(dst, NULL);
15556 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
15558 /* Test a blit without keying. */
15559 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, 0, &fx);
15560 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
15562 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15563 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
15564 color = surface_desc.lpSurface;
15565 /* Should have copied src data unmodified to dst. */
15566 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
15567 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
15568 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
15569 color[0], color[1], color[2], color[3], color[4], color[5]);
15571 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
15572 hr = IDirectDrawSurface4_Unlock(dst, NULL);
15573 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
15575 /* Src key. */
15576 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
15577 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
15579 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15580 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
15581 color = surface_desc.lpSurface;
15582 /* Src key applied to color[0]. It is unmodified, the others are copied. */
15583 ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
15584 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
15585 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
15586 color[0], color[1], color[2], color[3], color[4], color[5]);
15588 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
15589 hr = IDirectDrawSurface4_Unlock(dst, NULL);
15590 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
15592 /* Src override. */
15593 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
15594 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
15596 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15597 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
15598 color = surface_desc.lpSurface;
15599 /* Override key applied to color[5]. It is unmodified, the others are copied. */
15600 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
15601 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555,
15602 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
15603 color[0], color[1], color[2], color[3], color[4], color[5]);
15605 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
15606 hr = IDirectDrawSurface4_Unlock(dst, NULL);
15607 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
15609 /* Src override AND src key. That is not supposed to work. */
15610 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
15611 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
15613 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15614 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
15615 color = surface_desc.lpSurface;
15616 /* Ensure the destination was not changed. */
15617 ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 &&
15618 color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555,
15619 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
15620 color[0], color[1], color[2], color[3], color[4], color[5]);
15622 /* Use different dst colors for the dst key test. */
15623 color[0] = 0x00ff0000; /* Dest key in dst surface. */
15624 color[1] = 0x00ff0000; /* Dest key in dst surface. */
15625 color[2] = 0x00001100; /* Dest key in override. */
15626 color[3] = 0x00001100; /* Dest key in override. */
15627 color[4] = 0x000000aa; /* Dest key in src surface. */
15628 color[5] = 0x000000aa; /* Dest key in src surface. */
15629 hr = IDirectDrawSurface4_Unlock(dst, NULL);
15630 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
15632 /* Dest key blit. The key is taken from the DESTINATION surface in v4! */
15633 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
15634 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
15636 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15637 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
15638 color = surface_desc.lpSurface;
15639 /* Dst key applied to color[0,1], they are the only changed pixels. */
15640 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
15641 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
15642 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
15643 color[0], color[1], color[2], color[3], color[4], color[5]);
15645 color[0] = 0x00ff0000; /* Dest key in dst surface. */
15646 color[1] = 0x00ff0000; /* Dest key in dst surface. */
15647 color[2] = 0x00001100; /* Dest key in override. */
15648 color[3] = 0x00001100; /* Dest key in override. */
15649 color[4] = 0x000000aa; /* Dest key in src surface. */
15650 color[5] = 0x000000aa; /* Dest key in src surface. */
15651 hr = IDirectDrawSurface4_Unlock(dst, NULL);
15652 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
15654 /* What happens with a QI'd older version of the interface? It takes the key
15655 * from the source surface. */
15656 hr = IDirectDrawSurface4_QueryInterface(src, &IID_IDirectDrawSurface, (void **)&src1);
15657 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#lx.\n", hr);
15658 hr = IDirectDrawSurface4_QueryInterface(dst, &IID_IDirectDrawSurface, (void **)&dst1);
15659 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#lx.\n", hr);
15661 hr = IDirectDrawSurface_Blt(dst1, NULL, src1, NULL, DDBLT_KEYDEST, &fx);
15662 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
15664 IDirectDrawSurface_Release(dst1);
15665 IDirectDrawSurface_Release(src1);
15667 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15668 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
15669 color = surface_desc.lpSurface;
15670 /* Dst key applied to color[4,5], they are the only changed pixels. */
15671 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
15672 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
15673 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
15674 color[0], color[1], color[2], color[3], color[4], color[5]);
15676 color[0] = 0x00ff0000; /* Dest key in dst surface. */
15677 color[1] = 0x00ff0000; /* Dest key in dst surface. */
15678 color[2] = 0x00001100; /* Dest key in override. */
15679 color[3] = 0x00001100; /* Dest key in override. */
15680 color[4] = 0x000000aa; /* Dest key in src surface. */
15681 color[5] = 0x000000aa; /* Dest key in src surface. */
15682 hr = IDirectDrawSurface7_Unlock(dst, NULL);
15683 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
15685 /* Dest override key blit. */
15686 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
15687 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
15689 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15690 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
15691 color = surface_desc.lpSurface;
15692 /* Dst key applied to color[2,3], they are the only changed pixels. */
15693 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 &&
15694 color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa,
15695 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
15696 color[0], color[1], color[2], color[3], color[4], color[5]);
15698 color[0] = 0x00ff0000; /* Dest key in dst surface. */
15699 color[1] = 0x00ff0000; /* Dest key in dst surface. */
15700 color[2] = 0x00001100; /* Dest key in override. */
15701 color[3] = 0x00001100; /* Dest key in override. */
15702 color[4] = 0x000000aa; /* Dest key in src surface. */
15703 color[5] = 0x000000aa; /* Dest key in src surface. */
15704 hr = IDirectDrawSurface4_Unlock(dst, NULL);
15705 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
15707 /* Dest override together with surface key. Supposed to fail. */
15708 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
15709 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
15711 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15712 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
15713 color = surface_desc.lpSurface;
15714 /* Destination is unchanged. */
15715 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
15716 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
15717 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
15718 color[0], color[1], color[2], color[3], color[4], color[5]);
15719 hr = IDirectDrawSurface4_Unlock(dst, NULL);
15720 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
15722 /* Source and destination key. This is driver dependent. New HW treats it like
15723 * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */
15724 if (0)
15726 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
15727 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
15729 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15730 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
15731 color = surface_desc.lpSurface;
15732 /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if
15733 * the driver applies it. */
15734 ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
15735 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
15736 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
15737 color[0], color[1], color[2], color[3], color[4], color[5]);
15739 color[0] = 0x00ff0000; /* Dest key in dst surface. */
15740 color[1] = 0x00ff0000; /* Dest key in dst surface. */
15741 color[2] = 0x00001100; /* Dest key in override. */
15742 color[3] = 0x00001100; /* Dest key in override. */
15743 color[4] = 0x000000aa; /* Dest key in src surface. */
15744 color[5] = 0x000000aa; /* Dest key in src surface. */
15745 hr = IDirectDrawSurface4_Unlock(dst, NULL);
15746 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
15749 /* Override keys without ddbltfx parameter fail */
15750 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
15751 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
15752 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
15753 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
15755 /* Try blitting without keys in the source surface. */
15756 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, NULL);
15757 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
15758 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_DESTBLT, NULL);
15759 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
15761 /* That fails now. Do not bother to check that the data is unmodified. */
15762 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
15763 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
15765 /* Dest key blit still works, the destination surface key is used in v4. */
15766 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
15767 ok(SUCCEEDED(hr), "Failed to blit, hr %#lx.\n", hr);
15769 hr = IDirectDrawSurface4_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15770 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
15771 color = surface_desc.lpSurface;
15772 /* Dst key applied to color[0,1], they are the only changed pixels. */
15773 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
15774 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
15775 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
15776 color[0], color[1], color[2], color[3], color[4], color[5]);
15777 hr = IDirectDrawSurface4_Unlock(dst, NULL);
15778 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
15780 /* Try blitting without keys in the destination surface. */
15781 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, NULL);
15782 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
15783 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_DESTBLT, NULL);
15784 ok(SUCCEEDED(hr), "Failed to set color key, hr %#lx.\n", hr);
15786 /* This fails, as sanity would dictate. */
15787 hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
15788 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
15790 done:
15791 IDirectDrawSurface4_Release(src);
15792 IDirectDrawSurface4_Release(dst);
15793 refcount = IDirectDraw4_Release(ddraw);
15794 ok(!refcount, "DirectDraw has %lu references left.\n", refcount);
15795 DestroyWindow(window);
15798 static void test_vb_refcount(void)
15800 ULONG prev_d3d_refcount, prev_device_refcount;
15801 ULONG cur_d3d_refcount, cur_device_refcount;
15802 IDirect3DVertexBuffer *vb, *vb1;
15803 IDirect3DVertexBuffer7 *vb7;
15804 D3DVERTEXBUFFERDESC vb_desc;
15805 IDirect3DDevice3 *device;
15806 IDirect3D3 *d3d;
15807 ULONG refcount;
15808 IUnknown *unk;
15809 HWND window;
15810 HRESULT hr;
15812 window = create_window();
15813 if (!(device = create_device(window, DDSCL_NORMAL)))
15815 skip("Failed to create a 3D device, skipping test.\n");
15816 DestroyWindow(window);
15817 return;
15820 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
15821 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#lx.\n", hr);
15823 prev_d3d_refcount = get_refcount((IUnknown *)d3d);
15824 prev_device_refcount = get_refcount((IUnknown *)device);
15826 memset(&vb_desc, 0, sizeof(vb_desc));
15827 vb_desc.dwSize = sizeof(vb_desc);
15828 vb_desc.dwFVF = D3DFVF_XYZ;
15829 vb_desc.dwNumVertices = 4;
15830 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &vb, 0, NULL);
15831 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#lx.\n", hr);
15833 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
15834 cur_device_refcount = get_refcount((IUnknown *)device);
15835 ok(cur_d3d_refcount == prev_d3d_refcount, "D3D object refcount changed from %lu to %lu.\n",
15836 prev_d3d_refcount, cur_d3d_refcount);
15837 ok(cur_device_refcount == prev_device_refcount, "Device refcount changed from %lu to %lu.\n",
15838 prev_device_refcount, cur_device_refcount);
15840 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IDirect3DVertexBuffer, (void **)&vb1);
15841 ok(hr == DD_OK, "Failed to query IDirect3DVertexBuffer, hr %#lx.\n", hr);
15842 IDirect3DVertexBuffer_Release(vb1);
15844 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IDirect3DVertexBuffer7, (void **)&vb7);
15845 ok(hr == E_NOINTERFACE, "Querying IDirect3DVertexBuffer7 returned unexpected hr %#lx.\n", hr);
15847 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IUnknown, (void **)&unk);
15848 ok(hr == DD_OK, "Failed to query IUnknown, hr %#lx.\n", hr);
15849 ok((IUnknown *)vb == unk,
15850 "IDirect3DVertexBuffer and IUnknown interface pointers don't match, %p != %p.\n", vb, unk);
15851 IUnknown_Release(unk);
15853 refcount = IDirect3DVertexBuffer_Release(vb);
15854 ok(!refcount, "Vertex buffer has %lu references left.\n", refcount);
15855 IDirect3D3_Release(d3d);
15856 refcount = IDirect3DDevice3_Release(device);
15857 ok(!refcount, "Device has %lu references left.\n", refcount);
15858 DestroyWindow(window);
15861 static void test_compute_sphere_visibility(void)
15863 static D3DMATRIX proj_1 =
15865 1.810660f, 0.000000f, 0.000000f, 0.000000f,
15866 0.000000f, 2.414213f, 0.000000f, 0.000000f,
15867 0.000000f, 0.000000f, 1.020408f, 1.000000f,
15868 0.000000f, 0.000000f, -0.102041f, 0.000000f,
15870 static D3DMATRIX proj_2 =
15872 10.0f, 0.0f, 0.0f, 0.0f,
15873 0.0f, 10.0f, 0.0f, 0.0f,
15874 0.0f, 0.0f, 10.0f, 0.0f,
15875 0.0f, 0.0f, 0.0f, 1.0f,
15877 static D3DMATRIX view_1 =
15879 1.000000f, 0.000000f, 0.000000f, 0.000000f,
15880 0.000000f, 0.768221f, -0.640185f, 0.000000f,
15881 -0.000000f, 0.640185f, 0.768221f, 0.000000f,
15882 -14.852037f, 9.857489f, 11.600972f, 1.000000f,
15884 static D3DMATRIX identity =
15886 1.0f, 0.0f, 0.0f, 0.0f,
15887 0.0f, 1.0f, 0.0f, 0.0f,
15888 0.0f, 0.0f, 1.0f, 0.0f,
15889 0.0f, 0.0f, 0.0f, 1.0f,
15891 static struct
15893 D3DMATRIX *view, *proj;
15894 unsigned int sphere_count;
15895 D3DVECTOR center[3];
15896 D3DVALUE radius[3];
15897 const DWORD expected[3];
15898 BOOL todo;
15900 tests[] =
15902 {&view_1, &proj_1, 1, {{{11.461533f}, {-4.761727f}, {-1.171646f}}}, {38.252632f}, {0x1555}},
15903 {&view_1, &proj_1, 3, {{{-3.515620f}, {-1.560661f}, {-12.464638f}},
15904 {{14.290396f}, {-2.981143f}, {-24.311312f}},
15905 {{1.461626f}, {-6.093709f}, {-13.901010f}}},
15906 {4.354097f, 12.500704f, 17.251318f}, {0x154a, 0x1555, 0x1555}},
15907 {&identity, &proj_2, 1, {{{0.0f}, {0.0f}, {0.05f}}}, {0.04f}, {0x1555}, TRUE},
15908 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.5f}}}, {0.5f}, {0x1401}},
15909 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {0.0f}, {0x401}},
15910 {&identity, &identity, 1, {{{-1.0f}, {-1.0f}, {0.5f}}}, {0.25f}, {0x1505}, TRUE}, /* 5 */
15911 {&identity, &identity, 1, {{{-20.0f}, {0.0f}, {0.5f}}}, {3.0f}, {0x154a}},
15912 {&identity, &identity, 1, {{{20.0f}, {0.0f}, {0.5f}}}, {3.0f}, {0x1562}},
15913 {&identity, &identity, 1, {{{0.0f}, {-20.0f}, {0.5f}}}, {3.0f}, {0x1616}},
15914 {&identity, &identity, 1, {{{0.0f}, {20.0f}, {0.5f}}}, {3.0f}, {0x1496}},
15915 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {-20.0f}}}, {3.0f}, {0x956}}, /* 10 */
15916 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {20.0f}}}, {3.0f}, {0x2156}},
15918 IDirect3DViewport3 *viewport;
15919 IDirect3DDevice3 *device;
15920 unsigned int i, j;
15921 DWORD result[3];
15922 ULONG refcount;
15923 HWND window;
15924 HRESULT hr;
15926 window = create_window();
15927 if (!(device = create_device(window, DDSCL_NORMAL)))
15929 skip("Failed to create a 3D device, skipping test.\n");
15930 DestroyWindow(window);
15931 return;
15934 viewport = create_viewport(device, 0, 0, 640, 480);
15935 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
15936 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
15938 IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
15940 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15942 IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, tests[i].view);
15943 IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].proj);
15945 hr = IDirect3DDevice3_ComputeSphereVisibility(device, tests[i].center, tests[i].radius,
15946 tests[i].sphere_count, 0, result);
15947 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
15949 for (j = 0; j < tests[i].sphere_count; ++j)
15950 todo_wine_if(tests[i].todo)
15951 ok(result[j] == tests[i].expected[j], "Test %u sphere %u: expected %#lx, got %#lx.\n",
15952 i, j, tests[i].expected[j], result[j]);
15955 destroy_viewport(device, viewport);
15956 refcount = IDirect3DDevice3_Release(device);
15957 ok(!refcount, "Device has %lu references left.\n", refcount);
15958 DestroyWindow(window);
15961 static void test_texture_stages_limits(void)
15963 IDirectDrawSurface4 *surface;
15964 DDSURFACEDESC2 surface_desc;
15965 IDirect3DTexture2 *texture;
15966 IDirect3DDevice3 *device;
15967 IDirectDraw4 *ddraw;
15968 IDirect3D3 *d3d;
15969 unsigned int i;
15970 ULONG refcount;
15971 HWND window;
15972 HRESULT hr;
15974 window = create_window();
15975 if (!(device = create_device(window, DDSCL_NORMAL)))
15977 skip("Failed to create 3D device.\n");
15978 DestroyWindow(window);
15979 return;
15981 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
15982 ok(SUCCEEDED(hr), "Failed to get Direct3D interface, hr %#lx.\n", hr);
15983 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
15984 ok(SUCCEEDED(hr), "Failed to get DirectDraw interface, hr %#lx.\n", hr);
15985 IDirect3D3_Release(d3d);
15987 memset(&surface_desc, 0, sizeof(surface_desc));
15988 surface_desc.dwSize = sizeof(surface_desc);
15989 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
15990 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
15991 surface_desc.dwWidth = 16;
15992 surface_desc.dwHeight = 16;
15993 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
15994 ok(hr == DD_OK, "Failed to create surface, hr %#lx.\n", hr);
15995 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
15996 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#lx.\n", hr);
15997 IDirectDrawSurface4_Release(surface);
15999 for (i = 0; i < 8; ++i)
16001 hr = IDirect3DDevice3_SetTexture(device, i, texture);
16002 ok(hr == D3D_OK, "Failed to set texture %u, hr %#lx.\n", i, hr);
16003 hr = IDirect3DDevice3_SetTexture(device, i, NULL);
16004 ok(hr == D3D_OK, "Failed to set texture %u, hr %#lx.\n", i, hr);
16005 hr = IDirect3DDevice3_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
16006 ok(hr == D3D_OK, "Failed to set texture stage state %u, hr %#lx.\n", i, hr);
16009 IDirectDraw4_Release(ddraw);
16010 IDirect3DTexture2_Release(texture);
16011 refcount = IDirect3DDevice3_Release(device);
16012 ok(!refcount, "Device has %lu references left.\n", refcount);
16013 DestroyWindow(window);
16016 static void test_set_render_state(void)
16018 IDirect3DDevice3 *device;
16019 ULONG refcount;
16020 HWND window;
16021 DWORD state;
16022 HRESULT hr;
16024 window = create_window();
16025 if (!(device = create_device(window, DDSCL_NORMAL)))
16027 skip("Failed to create 3D device.\n");
16028 DestroyWindow(window);
16029 return;
16032 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, TRUE);
16033 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16034 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, FALSE);
16035 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16037 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
16038 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16039 state = 0xdeadbeef;
16040 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, &state);
16041 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16042 ok(!state, "Got unexpected render state %#lx.\n", state);
16043 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
16044 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16045 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, &state);
16046 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
16047 ok(state == D3DTBLEND_MODULATE, "Got unexpected render state %#lx.\n", state);
16049 refcount = IDirect3DDevice3_Release(device);
16050 ok(!refcount, "Device has %lu references left.\n", refcount);
16051 DestroyWindow(window);
16054 static void test_map_synchronisation(void)
16056 LARGE_INTEGER frequency, diff, ts[3];
16057 unsigned int i, j, tri_count, colour;
16058 IDirect3DVertexBuffer *buffer;
16059 IDirect3DViewport3 *viewport;
16060 D3DVERTEXBUFFERDESC vb_desc;
16061 IDirect3DDevice3 *device;
16062 BOOL unsynchronised, ret;
16063 IDirectDrawSurface4 *rt;
16064 IDirect3D3 *d3d;
16065 ULONG refcount;
16066 HWND window;
16067 HRESULT hr;
16069 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
16071 /* DDLOCK_DISCARDCONTENTS and DDLOCK_NOOVERWRITE were introduced with
16072 * ddraw7 and are ignored in earlier versions. */
16073 static const struct
16075 unsigned int flags;
16076 BOOL unsynchronised;
16078 tests[] =
16080 {0, FALSE},
16081 {DDLOCK_NOOVERWRITE, FALSE},
16082 {DDLOCK_DISCARDCONTENTS, FALSE},
16083 {DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS, FALSE},
16086 static const struct quad
16088 struct
16090 struct vec3 position;
16091 DWORD diffuse;
16092 } strip[4];
16094 quad1 =
16097 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
16098 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
16099 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
16100 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
16103 quad2 =
16106 {{-1.0f, -1.0f, 0.0f}, 0xffffff00},
16107 {{-1.0f, 1.0f, 0.0f}, 0xffffff00},
16108 {{ 1.0f, -1.0f, 0.0f}, 0xffffff00},
16109 {{ 1.0f, 1.0f, 0.0f}, 0xffffff00},
16112 struct quad *quads;
16114 window = create_window();
16115 ok(!!window, "Failed to create a window.\n");
16117 if (!(device = create_device(window, DDSCL_NORMAL)))
16119 skip("Failed to create a D3D device, skipping tests.\n");
16120 DestroyWindow(window);
16121 return;
16124 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
16125 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#lx.\n", hr);
16127 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
16128 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
16129 viewport = create_viewport(device, 0, 0, 640, 480);
16130 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
16131 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
16133 tri_count = 0x1000;
16135 ret = QueryPerformanceFrequency(&frequency);
16136 ok(ret, "Failed to get performance counter frequency.\n");
16138 vb_desc.dwSize = sizeof(vb_desc);
16139 vb_desc.dwCaps = D3DVBCAPS_WRITEONLY;
16140 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
16141 vb_desc.dwNumVertices = tri_count + 2;
16142 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0, NULL);
16143 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#lx.\n", hr);
16144 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
16145 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#lx.\n", hr);
16146 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
16148 quads[j] = quad1;
16150 hr = IDirect3DVertexBuffer_Unlock(buffer);
16151 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#lx.\n", hr);
16153 /* Initial draw to initialise states, compile shaders, etc. */
16154 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
16155 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
16156 hr = IDirect3DDevice3_BeginScene(device);
16157 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
16158 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
16159 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
16160 hr = IDirect3DDevice3_EndScene(device);
16161 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
16162 /* Read the result to ensure the GPU has finished drawing. */
16163 colour = get_surface_color(rt, 320, 240);
16165 /* Time drawing tri_count triangles. */
16166 ret = QueryPerformanceCounter(&ts[0]);
16167 ok(ret, "Failed to read performance counter.\n");
16168 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
16169 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
16170 hr = IDirect3DDevice3_BeginScene(device);
16171 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
16172 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
16173 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
16174 hr = IDirect3DDevice3_EndScene(device);
16175 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
16176 colour = get_surface_color(rt, 320, 240);
16177 /* Time drawing a single triangle. */
16178 ret = QueryPerformanceCounter(&ts[1]);
16179 ok(ret, "Failed to read performance counter.\n");
16180 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
16181 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
16182 hr = IDirect3DDevice3_BeginScene(device);
16183 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
16184 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 3, 0);
16185 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
16186 hr = IDirect3DDevice3_EndScene(device);
16187 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
16188 colour = get_surface_color(rt, 320, 240);
16189 ret = QueryPerformanceCounter(&ts[2]);
16190 ok(ret, "Failed to read performance counter.\n");
16192 IDirect3DVertexBuffer_Release(buffer);
16194 /* Estimate the number of triangles we can draw in 100ms. */
16195 diff.QuadPart = ts[1].QuadPart - ts[0].QuadPart + ts[1].QuadPart - ts[2].QuadPart;
16196 tri_count = (tri_count * frequency.QuadPart) / (diff.QuadPart * 10);
16197 tri_count = ((tri_count + 2 + 3) & ~3) - 2;
16198 vb_desc.dwNumVertices = tri_count + 2;
16200 for (i = 0; i < ARRAY_SIZE(tests); ++i)
16202 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0, NULL);
16203 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#lx.\n", hr);
16204 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
16205 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#lx.\n", hr);
16206 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
16208 quads[j] = quad1;
16210 hr = IDirect3DVertexBuffer_Unlock(buffer);
16211 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#lx.\n", hr);
16213 /* Start a draw operation. */
16214 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
16215 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
16216 hr = IDirect3DDevice3_BeginScene(device);
16217 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
16218 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
16219 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
16220 hr = IDirect3DDevice3_EndScene(device);
16221 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
16223 /* Map the last quad while the draw is in progress. */
16224 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_WAIT | tests[i].flags, (void **)&quads, NULL);
16225 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#lx.\n", hr);
16226 quads[(vb_desc.dwNumVertices / 4) - 1] = quad2;
16227 hr = IDirect3DVertexBuffer_Unlock(buffer);
16228 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#lx.\n", hr);
16230 colour = get_surface_color(rt, 320, 240);
16231 unsynchronised = compare_color(colour, 0x00ffff00, 1);
16232 ok(tests[i].unsynchronised == unsynchronised, "Expected %s map for flags %#x.\n",
16233 tests[i].unsynchronised ? "unsynchronised" : "synchronised", tests[i].flags);
16235 IDirect3DVertexBuffer_Release(buffer);
16238 destroy_viewport(device, viewport);
16239 IDirectDrawSurface4_Release(rt);
16240 IDirect3D3_Release(d3d);
16241 refcount = IDirect3DDevice3_Release(device);
16242 ok(!refcount, "Device has %lu references left.\n", refcount);
16243 DestroyWindow(window);
16246 static void test_depth_readback(void)
16248 unsigned int depth, expected_depth, i, x, y, max_diff, passed_fmts = 0;
16249 IDirectDrawSurface4 *rt, *ds;
16250 IDirect3DViewport3 *viewport;
16251 DDSURFACEDESC2 surface_desc;
16252 IDirect3DDevice3 *device;
16253 IDirectDraw4 *ddraw;
16254 IDirect3D3 *d3d;
16255 ULONG refcount;
16256 HWND window;
16257 HRESULT hr;
16258 RECT r;
16259 BOOL all_pass;
16261 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
16262 static struct
16264 struct vec3 position;
16265 DWORD diffuse;
16267 quad[] =
16269 {{-1.0f, -1.0f, 0.1f}, 0xff00ff00},
16270 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
16271 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
16272 {{ 1.0f, 1.0f, 0.9f}, 0xff00ff00},
16275 static const struct
16277 unsigned int z_depth, s_depth, z_mask, s_mask;
16278 BOOL todo;
16280 tests[] =
16282 {16, 0, 0x0000ffff, 0x00000000},
16283 {24, 0, 0x00ffffff, 0x00000000},
16284 {32, 0, 0x00ffffff, 0x00000000},
16285 {32, 8, 0x00ffffff, 0xff000000, TRUE},
16286 {32, 0, 0xffffffff, 0x00000000},
16289 window = create_window();
16290 ok(!!window, "Failed to create a window.\n");
16292 if (!(device = create_device(window, DDSCL_NORMAL)))
16294 skip("Failed to create a D3D device, skipping tests.\n");
16295 DestroyWindow(window);
16296 return;
16299 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
16300 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#lx.\n", hr);
16301 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
16302 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#lx.\n", hr);
16304 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
16305 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
16306 viewport = create_viewport(device, 0, 0, 640, 480);
16307 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
16308 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
16310 ds = get_depth_stencil(device);
16311 hr = IDirectDrawSurface4_DeleteAttachedSurface(rt, 0, ds);
16312 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#lx.\n", hr);
16313 IDirectDrawSurface4_Release(ds);
16315 for (i = 0; i < ARRAY_SIZE(tests); ++i)
16317 memset(&surface_desc, 0, sizeof(surface_desc));
16318 surface_desc.dwSize = sizeof(surface_desc);
16319 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
16320 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
16321 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
16322 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
16323 if (tests[i].s_depth)
16324 U4(surface_desc).ddpfPixelFormat.dwFlags |= DDPF_STENCILBUFFER;
16325 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = tests[i].z_depth;
16326 U2(U4(surface_desc).ddpfPixelFormat).dwStencilBitDepth = tests[i].s_depth;
16327 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = tests[i].z_mask;
16328 U4(U4(surface_desc).ddpfPixelFormat).dwStencilBitMask = tests[i].s_mask;
16329 surface_desc.dwWidth = 640;
16330 surface_desc.dwHeight = 480;
16331 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
16332 if (FAILED(hr))
16334 skip("Format %u not supported, skipping test.\n", i);
16335 continue;
16338 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
16339 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#lx.\n", hr);
16340 hr = IDirect3DDevice3_SetRenderTarget(device, rt, 0);
16341 ok(SUCCEEDED(hr), "Failed to set render target, hr %#lx.\n", hr);
16343 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
16344 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
16345 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
16346 hr = IDirect3DDevice3_BeginScene(device);
16347 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
16348 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
16349 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
16350 hr = IDirect3DDevice3_EndScene(device);
16351 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
16353 all_pass = TRUE;
16354 for (y = 60; y < 480; y += 120)
16356 for (x = 80; x < 640; x += 160)
16358 SetRect(&r, x, y, x + 1, y + 1);
16359 memset(&surface_desc, 0, sizeof(surface_desc));
16360 surface_desc.dwSize = sizeof(surface_desc);
16361 hr = IDirectDrawSurface4_Lock(ds, &r, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
16362 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
16364 depth = *((DWORD *)surface_desc.lpSurface) & tests[i].z_mask;
16365 expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
16366 max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
16367 /* The ddraw4 version of this test behaves similarly to the ddraw7 version on Nvidia GPUs,
16368 * except that Geforce 7 also returns garbage data in D24S8, whereas the ddraw7 version
16369 * returns 0 for that format. Give up on pre-filtering formats, accept Nvidia as generally
16370 * broken here, but still expect at least one format (D16 or D24X8 in practise) to pass.
16372 * Some of the tested places pass on some GPUs on Wine by accident. */
16373 todo_wine_if(tests[i].todo && !compare_uint(expected_depth, depth, max_diff))
16374 ok(compare_uint(expected_depth, depth, max_diff) || ddraw_is_nvidia(ddraw)
16375 || (ddraw_is_amd(ddraw) && !tests[i].s_depth && tests[i].z_mask == 0x00ffffff),
16376 "Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
16377 i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
16378 if (!compare_uint(expected_depth, depth, max_diff))
16379 all_pass = FALSE;
16381 hr = IDirectDrawSurface4_Unlock(ds, &r);
16382 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
16386 if (all_pass)
16387 passed_fmts++;
16389 hr = IDirectDrawSurface4_DeleteAttachedSurface(rt, 0, ds);
16390 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#lx.\n", hr);
16391 IDirectDrawSurface4_Release(ds);
16394 ok(passed_fmts, "Not a single format passed the tests, this is bad even by Nvidia's standards.\n");
16396 destroy_viewport(device, viewport);
16397 IDirectDrawSurface4_Release(rt);
16398 IDirectDraw4_Release(ddraw);
16399 IDirect3D3_Release(d3d);
16400 refcount = IDirect3DDevice3_Release(device);
16401 ok(!refcount, "Device has %lu references left.\n", refcount);
16402 DestroyWindow(window);
16405 static void test_clear(void)
16407 D3DRECT rect_negneg, rect_full = {{0}, {0}, {640}, {480}};
16408 IDirect3DViewport3 *viewport, *viewport2, *viewport3;
16409 IDirect3DDevice3 *device;
16410 IDirectDrawSurface4 *rt;
16411 IDirectDraw4 *ddraw;
16412 unsigned int color;
16413 IDirect3D3 *d3d;
16414 D3DRECT rect[2];
16415 ULONG refcount;
16416 HWND window;
16417 HRESULT hr;
16419 window = create_window();
16420 if (!(device = create_device(window, DDSCL_NORMAL)))
16422 skip("Failed to create 3D device.\n");
16423 DestroyWindow(window);
16424 return;
16427 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
16428 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#lx.\n", hr);
16429 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
16430 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#lx.\n", hr);
16432 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
16433 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
16435 viewport = create_viewport(device, 0, 0, 640, 480);
16436 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
16437 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
16439 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
16440 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
16442 /* Positive x, negative y. */
16443 U1(rect[0]).x1 = 0;
16444 U2(rect[0]).y1 = 480;
16445 U3(rect[0]).x2 = 320;
16446 U4(rect[0]).y2 = 240;
16448 /* Positive x, positive y. */
16449 U1(rect[1]).x1 = 0;
16450 U2(rect[1]).y1 = 0;
16451 U3(rect[1]).x2 = 320;
16452 U4(rect[1]).y2 = 240;
16454 /* Clear 2 rectangles with one call. Unlike d3d8/9, the refrast does not
16455 * refuse negative rectangles, but it will not clear them either. */
16456 hr = IDirect3DViewport3_Clear2(viewport, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
16457 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
16459 color = get_surface_color(rt, 160, 360);
16460 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 3 (pos, neg) has color 0x%08x.\n", color);
16461 color = get_surface_color(rt, 160, 120);
16462 ok(compare_color(color, 0x00ff0000, 0), "Clear rectangle 1 (pos, pos) has color 0x%08x.\n", color);
16463 color = get_surface_color(rt, 480, 360);
16464 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (NULL) has color 0x%08x.\n", color);
16465 color = get_surface_color(rt, 480, 120);
16466 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (neg, neg) has color 0x%08x.\n", color);
16468 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
16469 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
16470 /* negative x, negative y.
16471 * Also ignored, except on WARP, which clears the entire screen. */
16472 U1(rect_negneg).x1 = 640;
16473 U2(rect_negneg).y1 = 240;
16474 U3(rect_negneg).x2 = 320;
16475 U4(rect_negneg).y2 = 0;
16476 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
16477 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
16479 color = get_surface_color(rt, 160, 360);
16480 ok(compare_color(color, 0x00ffffff, 0)
16481 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
16482 "Got unexpected color 0x%08x.\n", color);
16483 color = get_surface_color(rt, 160, 120);
16484 ok(compare_color(color, 0x00ffffff, 0)
16485 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
16486 "Got unexpected color 0x%08x.\n", color);
16487 color = get_surface_color(rt, 480, 360);
16488 ok(compare_color(color, 0x00ffffff, 0)
16489 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
16490 "Got unexpected color 0x%08x.\n", color);
16491 color = get_surface_color(rt, 480, 120);
16492 ok(compare_color(color, 0x00ffffff, 0)
16493 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
16494 "Got unexpected color 0x%08x.\n", color);
16496 /* Test how the viewport affects clears. */
16497 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
16498 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
16500 viewport2 = create_viewport(device, 160, 120, 160, 120);
16501 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport2);
16502 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
16504 hr = IDirect3DViewport3_Clear2(viewport2, 1, &rect_full, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
16505 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
16507 viewport3 = create_viewport(device, 320, 240, 320, 240);
16508 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
16509 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
16511 U1(rect[0]).x1 = 160;
16512 U2(rect[0]).y1 = 120;
16513 U3(rect[0]).x2 = 480;
16514 U4(rect[0]).y2 = 360;
16515 hr = IDirect3DViewport3_Clear2(viewport3, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
16516 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
16518 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
16519 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#lx.\n", hr);
16521 color = get_surface_color(rt, 158, 118);
16522 ok(compare_color(color, 0x00ffffff, 0), "(158, 118) has color 0x%08x.\n", color);
16523 color = get_surface_color(rt, 162, 118);
16524 ok(compare_color(color, 0x00ffffff, 0), "(162, 118) has color 0x%08x.\n", color);
16525 color = get_surface_color(rt, 158, 122);
16526 ok(compare_color(color, 0x00ffffff, 0), "(158, 122) has color 0x%08x.\n", color);
16527 color = get_surface_color(rt, 162, 122);
16528 ok(compare_color(color, 0x000000ff, 0), "(162, 122) has color 0x%08x.\n", color);
16530 color = get_surface_color(rt, 318, 238);
16531 ok(compare_color(color, 0x000000ff, 0), "(318, 238) has color 0x%08x.\n", color);
16532 color = get_surface_color(rt, 322, 238);
16533 ok(compare_color(color, 0x00ffffff, 0), "(322, 328) has color 0x%08x.\n", color);
16534 color = get_surface_color(rt, 318, 242);
16535 ok(compare_color(color, 0x00ffffff, 0), "(318, 242) has color 0x%08x.\n", color);
16536 color = get_surface_color(rt, 322, 242);
16537 ok(compare_color(color, 0x0000ff00, 0), "(322, 242) has color 0x%08x.\n", color);
16539 color = get_surface_color(rt, 478, 358);
16540 ok(compare_color(color, 0x0000ff00, 0), "(478, 358) has color 0x%08x.\n", color);
16541 color = get_surface_color(rt, 482, 358);
16542 ok(compare_color(color, 0x00ffffff, 0), "(482, 358) has color 0x%08x.\n", color);
16543 color = get_surface_color(rt, 478, 362);
16544 ok(compare_color(color, 0x00ffffff, 0), "(478, 362) has color 0x%08x.\n", color);
16545 color = get_surface_color(rt, 482, 362);
16546 ok(compare_color(color, 0x00ffffff, 0), "(482, 362) has color 0x%08x.\n", color);
16548 /* The clear rectangle is rendertarget absolute, not relative to the
16549 * viewport. */
16550 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
16551 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
16552 U1(rect[0]).x1 = 330;
16553 U2(rect[0]).y1 = 250;
16554 U3(rect[0]).x2 = 340;
16555 U4(rect[0]).y2 = 260;
16556 hr = IDirect3DViewport3_Clear2(viewport3, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
16557 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
16559 color = get_surface_color(rt, 328, 248);
16560 ok(compare_color(color, 0x00ffffff, 0), "(328, 248) has color 0x%08x.\n", color);
16561 color = get_surface_color(rt, 332, 248);
16562 ok(compare_color(color, 0x00ffffff, 0), "(332, 248) has color 0x%08x.\n", color);
16563 color = get_surface_color(rt, 328, 252);
16564 ok(compare_color(color, 0x00ffffff, 0), "(328, 252) has color 0x%08x.\n", color);
16565 color = get_surface_color(rt, 332, 252);
16566 ok(compare_color(color, 0x0000ff00, 0), "(332, 252) has color 0x%08x.\n", color);
16568 color = get_surface_color(rt, 338, 248);
16569 ok(compare_color(color, 0x00ffffff, 0), "(338, 248) has color 0x%08x.\n", color);
16570 color = get_surface_color(rt, 342, 248);
16571 ok(compare_color(color, 0x00ffffff, 0), "(342, 248) has color 0x%08x.\n", color);
16572 color = get_surface_color(rt, 338, 252);
16573 ok(compare_color(color, 0x0000ff00, 0), "(338, 252) has color 0x%08x.\n", color);
16574 color = get_surface_color(rt, 342, 252);
16575 ok(compare_color(color, 0x00ffffff, 0), "(342, 252) has color 0x%08x.\n", color);
16577 color = get_surface_color(rt, 328, 258);
16578 ok(compare_color(color, 0x00ffffff, 0), "(328, 258) has color 0x%08x.\n", color);
16579 color = get_surface_color(rt, 332, 258);
16580 ok(compare_color(color, 0x0000ff00, 0), "(332, 258) has color 0x%08x.\n", color);
16581 color = get_surface_color(rt, 328, 262);
16582 ok(compare_color(color, 0x00ffffff, 0), "(328, 262) has color 0x%08x.\n", color);
16583 color = get_surface_color(rt, 332, 262);
16584 ok(compare_color(color, 0x00ffffff, 0), "(332, 262) has color 0x%08x.\n", color);
16586 color = get_surface_color(rt, 338, 258);
16587 ok(compare_color(color, 0x0000ff00, 0), "(338, 258) has color 0x%08x.\n", color);
16588 color = get_surface_color(rt, 342, 258);
16589 ok(compare_color(color, 0x00ffffff, 0), "(342, 258) has color 0x%08x.\n", color);
16590 color = get_surface_color(rt, 338, 262);
16591 ok(compare_color(color, 0x00ffffff, 0), "(338, 262) has color 0x%08x.\n", color);
16592 color = get_surface_color(rt, 342, 262);
16593 ok(compare_color(color, 0x00ffffff, 0), "(342, 262) has color 0x%08x.\n", color);
16595 /* COLORWRITEENABLE, SRGBWRITEENABLE and scissor rectangles do not exist
16596 * in d3d3. */
16598 IDirect3DViewport3_Release(viewport3);
16599 IDirect3DViewport3_Release(viewport2);
16600 IDirect3DViewport3_Release(viewport);
16601 IDirectDrawSurface4_Release(rt);
16602 IDirectDraw4_Release(ddraw);
16603 IDirect3D3_Release(d3d);
16604 refcount = IDirect3DDevice3_Release(device);
16605 ok(!refcount, "Device has %lu references left.\n", refcount);
16606 DestroyWindow(window);
16609 struct enum_surfaces_param
16611 IDirectDraw4 *ddraw;
16612 DDSURFACEDESC2 modes[20];
16613 unsigned int mode_count;
16615 IDirectDrawSurface4 *surfaces[8];
16616 unsigned int count;
16619 static HRESULT CALLBACK build_mode_list_cb(DDSURFACEDESC2 *desc, void *context)
16621 struct enum_surfaces_param *param = context;
16622 IDirectDrawSurface4 *surface;
16624 if (SUCCEEDED(IDirectDraw4_CreateSurface(param->ddraw, desc, &surface, NULL)))
16626 if (param->mode_count < ARRAY_SIZE(param->modes))
16627 param->modes[param->mode_count] = *desc;
16628 ++param->mode_count;
16629 IDirectDrawSurface4_Release(surface);
16632 return DDENUMRET_OK;
16635 static HRESULT WINAPI enum_surfaces_cb(IDirectDrawSurface4 *surface, DDSURFACEDESC2 *desc, void *context)
16637 struct enum_surfaces_param *param = context;
16638 BOOL found = FALSE;
16639 unsigned int i;
16641 for (i = 0; i < ARRAY_SIZE(param->surfaces); ++i)
16643 if (param->surfaces[i] == surface)
16645 found = TRUE;
16646 break;
16650 ok(found, "Unexpected surface %p enumerated.\n", surface);
16651 IDirectDrawSurface4_Release(surface);
16652 ++param->count;
16654 return DDENUMRET_OK;
16657 static HRESULT WINAPI enum_surfaces_create_cb(IDirectDrawSurface4 *surface, DDSURFACEDESC2 *desc, void *context)
16659 static const DWORD expect_flags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_PIXELFORMAT;
16660 struct enum_surfaces_param *param = context;
16662 ok(!surface, "Unexpected surface %p.\n", surface);
16663 ok((desc->dwFlags & expect_flags) == expect_flags, "Got unexpected flags %#lx.\n", desc->dwFlags);
16664 if (param->count < ARRAY_SIZE(param->modes))
16666 const DDSURFACEDESC2 *expect = &param->modes[param->count];
16667 ok(desc->dwWidth == expect->dwWidth, "Expected width %lu, got %lu.\n", expect->dwWidth, desc->dwWidth);
16668 ok(desc->dwHeight == expect->dwHeight, "Expected height %lu, got %lu.\n", expect->dwHeight, desc->dwHeight);
16669 ok(!memcmp(&U4(*desc).ddpfPixelFormat, &U4(*expect).ddpfPixelFormat, sizeof(U4(*desc).ddpfPixelFormat)),
16670 "Pixel formats didn't match.\n");
16673 ++param->count;
16675 return DDENUMRET_OK;
16678 static void test_enum_surfaces(void)
16680 struct enum_surfaces_param param = {0};
16681 DDPIXELFORMAT current_format;
16682 DDSURFACEDESC2 desc;
16683 IDirectDraw4 *ddraw;
16684 HRESULT hr;
16686 ddraw = create_ddraw();
16687 ok(!!ddraw, "Failed to create a ddraw object.\n");
16688 param.ddraw = ddraw;
16690 memset(&desc, 0, sizeof(desc));
16691 desc.dwSize = sizeof(desc);
16692 hr = IDirectDraw4_GetDisplayMode(ddraw, &desc);
16693 ok(hr == DD_OK, "Failed to get display mode, hr %#lx.\n", hr);
16694 current_format = U4(desc).ddpfPixelFormat;
16696 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
16697 ok(hr == DD_OK, "Failed to set cooperative level, hr %#lx.\n", hr);
16699 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_ALL, NULL, NULL, enum_surfaces_cb);
16700 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
16702 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_ALL,
16703 NULL, NULL, enum_surfaces_cb);
16704 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
16706 memset(&desc, 0, sizeof(desc));
16707 desc.dwSize = sizeof(desc);
16708 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
16709 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
16710 U2(desc).dwMipMapCount = 3;
16711 desc.dwWidth = 32;
16712 desc.dwHeight = 32;
16713 hr = IDirectDraw4_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL);
16714 ok(hr == DD_OK, "Failed to create a surface, hr %#lx.\n", hr);
16716 hr = IDirectDrawSurface4_GetAttachedSurface(param.surfaces[0], &desc.ddsCaps, &param.surfaces[1]);
16717 ok(hr == DD_OK, "Failed to get attached surface, hr %#lx.\n", hr);
16718 hr = IDirectDrawSurface4_GetAttachedSurface(param.surfaces[1], &desc.ddsCaps, &param.surfaces[2]);
16719 ok(hr == DD_OK, "Failed to get attached surface, hr %#lx.\n", hr);
16720 hr = IDirectDrawSurface4_GetAttachedSurface(param.surfaces[2], &desc.ddsCaps, &param.surfaces[3]);
16721 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
16722 ok(!param.surfaces[3], "Got unexpected pointer %p.\n", param.surfaces[3]);
16724 param.count = 0;
16725 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
16726 &desc, &param, enum_surfaces_cb);
16727 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
16728 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16730 param.count = 0;
16731 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
16732 NULL, &param, enum_surfaces_cb);
16733 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
16734 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16736 desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
16737 param.count = 0;
16738 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
16739 &desc, &param, enum_surfaces_cb);
16740 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
16741 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16743 param.count = 0;
16744 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_NOMATCH,
16745 &desc, &param, enum_surfaces_cb);
16746 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
16747 ok(param.count == 2, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16749 desc.dwFlags = 0;
16750 param.count = 0;
16751 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
16752 &desc, &param, enum_surfaces_cb);
16753 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
16754 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16756 desc.dwFlags = 0;
16757 param.count = 0;
16758 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST, &desc, &param, enum_surfaces_cb);
16759 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
16760 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16762 IDirectDrawSurface4_Release(param.surfaces[2]);
16763 IDirectDrawSurface4_Release(param.surfaces[1]);
16764 IDirectDrawSurface4_Release(param.surfaces[0]);
16766 param.count = 0;
16767 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
16768 NULL, &param, enum_surfaces_cb);
16769 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
16770 ok(!param.count, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16772 memset(&desc, 0, sizeof(desc));
16773 desc.dwSize = sizeof(desc);
16774 desc.dwFlags = DDSD_CAPS;
16775 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
16777 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_ALL,
16778 &desc, &param, enum_surfaces_create_cb);
16779 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#lx.\n", hr);
16781 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_NOMATCH,
16782 &desc, &param, enum_surfaces_create_cb);
16783 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#lx.\n", hr);
16785 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED,
16786 &desc, &param, enum_surfaces_create_cb);
16787 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#lx.\n", hr);
16789 /* When not passed width and height, the callback is called with every
16790 * available display resolution. */
16792 param.mode_count = 0;
16793 desc.dwFlags |= DDSD_PIXELFORMAT;
16794 U4(desc).ddpfPixelFormat = current_format;
16795 hr = IDirectDraw4_EnumDisplayModes(ddraw, 0, &desc, &param, build_mode_list_cb);
16796 ok(hr == DD_OK, "Failed to build mode list, hr %#lx.\n", hr);
16798 param.count = 0;
16799 desc.dwFlags &= ~DDSD_PIXELFORMAT;
16800 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
16801 &desc, &param, enum_surfaces_create_cb);
16802 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
16803 ok(param.count == param.mode_count, "Expected %u surfaces, got %u.\n", param.mode_count, param.count);
16805 desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
16806 desc.dwWidth = desc.dwHeight = 32;
16808 param.modes[0].dwWidth = param.modes[0].dwHeight = 32;
16810 param.count = 0;
16811 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
16812 &desc, &param, enum_surfaces_create_cb);
16813 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
16814 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16816 hr = IDirectDraw4_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL);
16817 ok(hr == DD_OK, "Failed to create surface, hr %#lx.\n", hr);
16818 param.count = 0;
16819 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
16820 &desc, &param, enum_surfaces_create_cb);
16821 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
16822 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16823 IDirectDrawSurface4_Release(param.surfaces[0]);
16825 desc.dwFlags |= DDSD_PIXELFORMAT;
16826 U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat);
16827 U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
16828 U4(desc).ddpfPixelFormat.dwFourCC = 0xdeadbeef;
16830 param.count = 0;
16831 hr = IDirectDraw4_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
16832 &desc, &param, enum_surfaces_create_cb);
16833 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#lx.\n", hr);
16834 ok(!param.count, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16836 IDirectDraw4_Release(ddraw);
16839 static void test_viewport(void)
16841 static struct
16843 D3DVIEWPORT7 vp;
16844 RECT expected_rect;
16845 const char *message;
16847 tests[] =
16849 {{ 0, 0, 640, 480}, { 0, 120, 479, 359}, "Viewport (0, 0) - (640, 480)"},
16850 {{ 0, 0, 320, 240}, { 0, 60, 239, 179}, "Viewport (0, 0) - (320, 240)"},
16851 {{ 0, 0, 1280, 960}, { 0, 240, 639, 479}, "Viewport (0, 0) - (1280, 960)"},
16852 {{ 0, 0, 2000, 1600}, { 0, 400, 639, 479}, "Viewport (0, 0) - (2000, 1600)"},
16853 {{100, 100, 640, 480}, {100, 220, 579, 459}, "Viewport (100, 100) - (640, 480)"},
16854 {{ 0, 0, 8192, 8192}, {-10, -10, -10, -10}, "Viewport (0, 0) - (8192, 8192)"},
16856 static const struct
16858 unsigned int x, y;
16860 rt_sizes[] =
16862 {640, 480}, {1280, 960}, {320, 240}, {800, 600},
16864 static D3DMATRIX mat =
16866 1.0f, 0.0f, 0.0f, 0.0f,
16867 0.0f, 1.0f, 0.0f, 0.0f,
16868 0.0f, 0.0f, 1.0f, 0.0f,
16869 0.0f, 0.0f, 0.0f, 1.0f,
16871 static struct vec3 quad[] =
16873 {-1.5f, -0.5f, 0.1f},
16874 {-1.5f, 0.5f, 0.1f},
16875 { 0.5f, -0.5f, 0.1f},
16876 { 0.5f, 0.5f, 0.1f},
16878 IDirect3DViewport3 *viewport, *full_viewport;
16879 IDirectDrawSurface4 *rt, *ds;
16880 DDSURFACEDESC2 surface_desc;
16881 IDirect3DDevice3 *device;
16882 BOOL expected_failure;
16883 IDirectDraw4 *ddraw;
16884 DDPIXELFORMAT z_fmt;
16885 D3DRECT clear_rect;
16886 unsigned int i, j;
16887 IDirect3D3 *d3d;
16888 D3DVIEWPORT2 vp;
16889 ULONG refcount;
16890 HWND window;
16891 HRESULT hr;
16893 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
16894 0, 0, 640, 480, 0, 0, 0, 0);
16895 if (!(device = create_device(window, DDSCL_NORMAL)))
16897 skip("Failed to create a 3D device, skipping test.\n");
16898 DestroyWindow(window);
16899 return;
16902 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
16903 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#lx.\n", hr);
16904 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
16905 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#lx.\n", hr);
16907 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
16908 ok(SUCCEEDED(hr), "Failed to disable depth test, hr %#lx.\n", hr);
16909 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
16910 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#lx.\n", hr);
16912 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
16913 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#lx.\n", hr);
16914 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
16915 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#lx.\n", hr);
16916 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
16917 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#lx.\n", hr);
16919 ds = get_depth_stencil(device);
16920 memset(&surface_desc, 0, sizeof(surface_desc));
16921 surface_desc.dwSize = sizeof(surface_desc);
16922 hr = IDirectDrawSurface4_GetSurfaceDesc(ds, &surface_desc);
16923 z_fmt = U4(surface_desc).ddpfPixelFormat;
16925 for (i = 0; i < ARRAY_SIZE(rt_sizes); ++i)
16927 winetest_push_context("Size %ux%u", rt_sizes[i].x, rt_sizes[i].y);
16929 if (i)
16931 memset(&surface_desc, 0, sizeof(surface_desc));
16932 surface_desc.dwSize = sizeof(surface_desc);
16933 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
16934 surface_desc.dwWidth = rt_sizes[i].x;
16935 surface_desc.dwHeight = rt_sizes[i].y;
16936 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
16937 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &rt, NULL);
16938 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16940 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
16941 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
16942 U4(surface_desc).ddpfPixelFormat = z_fmt;
16943 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
16944 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16945 hr = IDirectDrawSurface4_AddAttachedSurface(rt, ds);
16946 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16948 hr = IDirect3DDevice3_SetRenderTarget(device, rt, 0);
16949 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16951 else
16953 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
16954 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16957 full_viewport = create_viewport(device, 0, 0, rt_sizes[i].x, rt_sizes[i].y);
16959 U1(clear_rect).x1 = U2(clear_rect).y1 = 0;
16960 U3(clear_rect).x2 = rt_sizes[i].x;
16961 U4(clear_rect).y2 = rt_sizes[i].y;
16963 for (j = 0; j < ARRAY_SIZE(tests); ++j)
16965 winetest_push_context(tests[j].message);
16967 expected_failure = tests[j].vp.dwX + tests[j].vp.dwWidth > rt_sizes[i].x
16968 || tests[j].vp.dwY + tests[j].vp.dwHeight > rt_sizes[i].y;
16970 hr = IDirect3DViewport3_Clear2(full_viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff000000, 0.0f, 0);
16971 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16973 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
16974 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16975 hr = IDirect3DViewport3_SetViewport2(viewport, NULL);
16976 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
16977 memset(&vp, 0, sizeof(vp));
16978 vp.dwSize = sizeof(vp);
16979 vp.dwX = tests[j].vp.dwX;
16980 vp.dwY = tests[j].vp.dwY;
16981 vp.dwWidth = tests[j].vp.dwWidth;
16982 vp.dwHeight = tests[j].vp.dwHeight;
16983 vp.dvClipX = -1.0f;
16984 vp.dvClipY = 1.0f;
16985 vp.dvClipWidth = 2.0f;
16986 vp.dvClipHeight = 2.0f;
16987 vp.dvMinZ = 0.0f;
16988 vp.dvMaxZ = 1.0f;
16989 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
16990 ok(hr == D3DERR_VIEWPORTHASNODEVICE, "Got unexpected hr %#lx.\n", hr);
16991 hr = IDirect3DDevice3_AddViewport(device, viewport);
16992 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16993 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
16994 ok(hr == (expected_failure ? E_INVALIDARG : DD_OK), "Got unexpected hr %#lx.\n", hr);
16996 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
16997 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
16998 if (expected_failure)
17000 destroy_viewport(device, viewport);
17001 winetest_pop_context();
17002 continue;
17005 hr = IDirect3DDevice3_BeginScene(device);
17006 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17007 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
17008 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17009 hr = IDirect3DDevice3_EndScene(device);
17010 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17012 check_rect(rt, tests[j].expected_rect);
17014 destroy_viewport(device, viewport);
17015 winetest_pop_context();
17018 destroy_viewport(device, full_viewport);
17020 hr = IDirectDrawSurface4_DeleteAttachedSurface(rt, 0, ds);
17021 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#lx (i %u).\n", hr, i);
17022 IDirectDrawSurface4_Release(ds);
17024 IDirectDrawSurface4_Release(rt);
17026 winetest_pop_context();
17029 refcount = IDirect3DDevice3_Release(device);
17030 ok(!refcount, "Device has %lu references left.\n", refcount);
17031 IDirect3D3_Release(d3d);
17032 IDirectDraw4_Release(ddraw);
17033 DestroyWindow(window);
17036 static void test_find_device(void)
17038 D3DFINDDEVICESEARCH search = {0};
17039 D3DFINDDEVICERESULT result = {0};
17040 IDirect3DDevice3 *device;
17041 IDirectDraw4 *ddraw;
17042 IDirect3D3 *d3d;
17043 unsigned int i;
17044 HWND window;
17045 HRESULT hr;
17047 struct
17049 DWORD size;
17050 GUID guid;
17051 D3DDEVICEDESC_V1 hw_desc;
17052 D3DDEVICEDESC_V1 sw_desc;
17053 } result_v1;
17055 struct
17057 DWORD size;
17058 GUID guid;
17059 D3DDEVICEDESC_V2 hw_desc;
17060 D3DDEVICEDESC_V2 sw_desc;
17061 } result_v2;
17063 static const struct
17065 const GUID *guid;
17066 HRESULT hr;
17068 tests[] =
17070 {&IID_IDirect3D, DDERR_NOTFOUND},
17071 {&IID_IDirect3DRampDevice, DDERR_NOTFOUND},
17072 {&IID_IDirect3DRGBDevice, D3D_OK},
17073 {&IID_IDirect3DMMXDevice, DDERR_NOTFOUND},
17074 {&IID_IDirect3DRefDevice, DDERR_NOTFOUND},
17075 {&IID_IDirect3DTnLHalDevice, DDERR_NOTFOUND},
17076 {&IID_IDirect3DNullDevice, DDERR_NOTFOUND},
17079 ddraw = create_ddraw();
17080 ok(!!ddraw, "Failed to create a ddraw object.\n");
17082 if (FAILED(IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d)))
17084 skip("D3D interface is not available, skipping test.\n");
17085 IDirectDraw4_Release(ddraw);
17086 return;
17089 result.dwSize = sizeof(result);
17090 search.dwSize = sizeof(search);
17091 hr = IDirect3D3_FindDevice(d3d, NULL, NULL);
17092 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
17093 hr = IDirect3D3_FindDevice(d3d, NULL, &result);
17094 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
17095 hr = IDirect3D3_FindDevice(d3d, &search, NULL);
17096 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
17097 hr = IDirect3D3_FindDevice(d3d, &search, &result);
17098 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17099 ok(result.dwSize == sizeof(result), "Got unexpected result size %lu.\n", result.dwSize);
17100 ok(result.ddHwDesc.dwSize == sizeof(result.ddHwDesc),
17101 "Got unexpected HW desc size %lu.\n", result.ddHwDesc.dwSize);
17102 ok(result.ddSwDesc.dwSize == sizeof(result.ddSwDesc),
17103 "Got unexpected SW desc size %lu.\n", result.ddSwDesc.dwSize);
17105 memset(&search, 0, sizeof(search));
17106 memset(&result, 0, sizeof(result));
17107 hr = IDirect3D3_FindDevice(d3d, &search, &result);
17108 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
17110 search.dwSize = sizeof(search) + 1;
17111 result.dwSize = sizeof(result) + 1;
17112 hr = IDirect3D3_FindDevice(d3d, &search, &result);
17113 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
17115 search.dwSize = sizeof(search);
17117 memset(&result_v1, 0, sizeof(result_v1));
17118 result_v1.size = sizeof(result_v1);
17119 hr = IDirect3D3_FindDevice(d3d, &search, (D3DFINDDEVICERESULT *)&result_v1);
17120 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17121 ok(result_v1.hw_desc.dwSize == sizeof(result.ddHwDesc),
17122 "Got unexpected HW desc size %lu.\n", result_v1.hw_desc.dwSize);
17123 ok(result_v1.sw_desc.dwSize == sizeof(result.ddSwDesc),
17124 "Got unexpected SW desc size %lu.\n", result_v1.sw_desc.dwSize);
17126 memset(&result_v2, 0, sizeof(result_v2));
17127 result_v2.size = sizeof(result_v2);
17128 hr = IDirect3D3_FindDevice(d3d, &search, (D3DFINDDEVICERESULT *)&result_v2);
17129 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17130 ok(result_v2.hw_desc.dwSize == sizeof(result.ddHwDesc),
17131 "Got unexpected HW desc size %lu.\n", result_v2.hw_desc.dwSize);
17132 ok(result_v2.sw_desc.dwSize == sizeof(result.ddSwDesc),
17133 "Got unexpected SW desc size %lu.\n", result_v2.sw_desc.dwSize);
17135 for (i = 0; i < ARRAY_SIZE(tests); ++i)
17137 memset(&search, 0, sizeof(search));
17138 search.dwSize = sizeof(search);
17139 search.dwFlags = D3DFDS_GUID;
17140 search.guid = *tests[i].guid;
17142 memset(&result, 0, sizeof(result));
17143 result.dwSize = sizeof(result);
17145 hr = IDirect3D3_FindDevice(d3d, &search, &result);
17146 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#lx.\n", i, hr);
17147 ok(result.dwSize == sizeof(result), "Test %u: Got unexpected result size %lu.\n", i, result.dwSize);
17148 if (SUCCEEDED(hr))
17150 ok(result.ddHwDesc.dwSize == sizeof(result.ddHwDesc),
17151 "Test %u: Got unexpected HW desc size %lu.\n", i, result.ddHwDesc.dwSize);
17152 ok(result.ddSwDesc.dwSize == sizeof(result.ddSwDesc),
17153 "Test %u: Got unexpected SW desc size %lu.\n", i, result.ddSwDesc.dwSize);
17155 else
17157 ok(!result.ddHwDesc.dwSize,
17158 "Test %u: Got unexpected HW desc size %lu.\n", i, result.ddHwDesc.dwSize);
17159 ok(!result.ddSwDesc.dwSize,
17160 "Test %u: Got unexpected SW desc size %lu.\n", i, result.ddSwDesc.dwSize);
17164 /* The HAL device can only be enumerated if hardware acceleration is present. */
17165 search.dwSize = sizeof(search);
17166 search.dwFlags = D3DFDS_GUID;
17167 search.guid = IID_IDirect3DHALDevice;
17168 result.dwSize = sizeof(result);
17169 hr = IDirect3D3_FindDevice(d3d, &search, &result);
17171 window = create_window();
17172 device = create_device(window, DDSCL_NORMAL);
17173 if (hr == D3D_OK)
17174 ok(!!device, "Failed to create a 3D device.\n");
17175 else
17176 ok(!device, "Succeeded to create a 3D device.\n");
17177 if (device)
17178 IDirect3DDevice3_Release(device);
17179 DestroyWindow(window);
17181 /* Curiously the colour model criteria seem to be ignored. */
17182 search.dwSize = sizeof(search);
17183 search.dwFlags = D3DFDS_COLORMODEL;
17184 search.dcmColorModel = 0xdeadbeef;
17185 result.dwSize = sizeof(result);
17186 hr = IDirect3D3_FindDevice(d3d, &search, &result);
17187 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17189 IDirect3D3_Release(d3d);
17190 IDirectDraw4_Release(ddraw);
17193 static IDirectDraw4 *killfocus_ddraw;
17194 static IDirectDrawSurface4 *killfocus_surface;
17196 static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
17198 ULONG ref;
17200 if (message == WM_KILLFOCUS)
17202 ref = IDirectDrawSurface4_Release(killfocus_surface);
17203 ok(!ref, "Unexpected surface refcount %lu.\n", ref);
17204 ref = IDirectDraw4_Release(killfocus_ddraw);
17205 ok(!ref, "Unexpected ddraw refcount %lu.\n", ref);
17206 killfocus_ddraw = NULL;
17209 return DefWindowProcA(window, message, wparam, lparam);
17212 static void test_killfocus(void)
17214 DDSURFACEDESC2 surface_desc;
17215 HRESULT hr;
17216 HWND window;
17217 WNDCLASSA wc = {0};
17219 wc.lpfnWndProc = killfocus_proc;
17220 wc.lpszClassName = "ddraw_killfocus_wndproc_wc";
17221 ok(RegisterClassA(&wc), "Failed to register window class.\n");
17223 window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
17224 0, 0, 640, 480, 0, 0, 0, 0);
17226 killfocus_ddraw = create_ddraw();
17227 ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n");
17229 hr = IDirectDraw4_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
17230 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#lx.\n", hr);
17232 memset(&surface_desc, 0, sizeof(surface_desc));
17233 surface_desc.dwSize = sizeof(surface_desc);
17234 surface_desc.dwFlags = DDSD_CAPS;
17235 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
17236 hr = IDirectDraw4_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL);
17237 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
17239 SetForegroundWindow(GetDesktopWindow());
17240 ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n");
17242 DestroyWindow(window);
17243 UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
17246 static void test_sysmem_draw(void)
17248 D3DRECT rect_full = {{0}, {0}, {640}, {480}};
17249 IDirectDrawSurface4 *rt, *surface;
17250 IDirect3DViewport3 *viewport;
17251 DDSURFACEDESC2 surface_desc;
17252 D3DVERTEXBUFFERDESC vb_desc;
17253 IDirect3DTexture2 *texture;
17254 IDirect3DVertexBuffer *vb;
17255 IDirect3DDevice3 *device;
17256 IDirectDraw4 *ddraw;
17257 unsigned int color;
17258 IDirect3D3 *d3d;
17259 ULONG refcount;
17260 HWND window;
17261 HRESULT hr;
17262 BYTE *data;
17264 static const struct
17266 struct vec3 position;
17267 DWORD diffuse;
17269 quad[] =
17271 {{ 0.0f, 0.0f, 0.0f}, 0x00000000},
17272 {{ 0.0f, 0.0f, 0.0f}, 0x00000000},
17273 {{ 0.0f, 0.0f, 0.0f}, 0x00000000},
17274 {{ 0.0f, 0.0f, 0.0f}, 0x00000000},
17275 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
17276 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
17277 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
17278 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
17280 static WORD indices[] = {4, 5, 6, 7};
17282 window = create_window();
17283 ok(!!window, "Failed to create a window.\n");
17285 if (!(device = create_device(window, DDSCL_NORMAL)))
17287 skip("Failed to create a 3D device, skipping test.\n");
17288 DestroyWindow(window);
17289 return;
17292 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
17293 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17294 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
17295 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17296 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
17297 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17299 viewport = create_viewport(device, 0, 0, 640, 480);
17300 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
17301 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17303 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
17304 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17306 vb_desc.dwSize = sizeof(vb_desc);
17307 vb_desc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
17308 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
17309 vb_desc.dwNumVertices = ARRAY_SIZE(quad);
17310 hr = IDirect3D3_CreateVertexBuffer(d3d, &vb_desc, &vb, 0, NULL);
17311 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17313 hr = IDirect3DVertexBuffer_Lock(vb, 0, (void **)&data, NULL);
17314 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17315 memcpy(data, quad, sizeof(quad));
17316 hr = IDirect3DVertexBuffer_Unlock(vb);
17317 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17319 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
17320 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17322 hr = IDirect3DDevice3_BeginScene(device);
17323 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17324 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 4, 4, 0);
17325 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17326 hr = IDirect3DDevice3_EndScene(device);
17327 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17329 color = get_surface_color(rt, 320, 240);
17330 ok(compare_color(color, 0x00007f7f, 1), "Got unexpected color 0x%08x.\n", color);
17332 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
17333 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17335 hr = IDirect3DDevice3_BeginScene(device);
17336 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17337 hr = IDirect3DDevice3_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, indices, 4, 0);
17338 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17339 hr = IDirect3DDevice3_EndScene(device);
17340 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17342 color = get_surface_color(rt, 320, 240);
17343 ok(compare_color(color, 0x00007f7f, 1), "Got unexpected color 0x%08x.\n", color);
17345 memset(&surface_desc, 0, sizeof(surface_desc));
17346 surface_desc.dwSize = sizeof(surface_desc);
17347 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
17348 surface_desc.dwHeight = 2;
17349 surface_desc.dwWidth = 2;
17350 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
17351 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
17352 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
17353 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
17354 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
17355 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
17356 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
17357 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
17358 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
17359 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17360 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
17361 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17362 IDirectDrawSurface4_Release(surface);
17363 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
17364 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17366 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
17367 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17369 hr = IDirect3DDevice3_BeginScene(device);
17370 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17371 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
17372 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17373 hr = IDirect3DDevice3_EndScene(device);
17374 ok(hr == D3D_OK || hr == D3DERR_SCENE_END_FAILED, "Got unexpected hr %#lx.\n", hr);
17376 IDirect3DTexture2_Release(texture);
17377 IDirect3DVertexBuffer_Release(vb);
17378 IDirect3DViewport3_Release(viewport);
17379 IDirectDrawSurface4_Release(rt);
17380 IDirectDraw4_Release(ddraw);
17381 IDirect3D3_Release(d3d);
17382 refcount = IDirect3DDevice3_Release(device);
17383 ok(!refcount, "Device has %lu references left.\n", refcount);
17384 DestroyWindow(window);
17387 static void test_gdi_surface(void)
17389 IDirectDrawSurface4 *primary, *backbuffer, *gdi_surface;
17390 DDSCAPS2 caps = {DDSCAPS_BACKBUFFER, 0, 0, {0}};
17391 DDSURFACEDESC2 surface_desc;
17392 IDirectDraw4 *ddraw;
17393 ULONG refcount;
17394 HWND window;
17395 HRESULT hr;
17397 window = create_window();
17398 ddraw = create_ddraw();
17399 ok(!!ddraw, "Failed to create a ddraw object.\n");
17400 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
17401 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17403 /* Retrieving the GDI surface requires a primary surface to exist. */
17404 gdi_surface = (void *)0xc0dec0de;
17405 hr = IDirectDraw4_GetGDISurface(ddraw, &gdi_surface);
17406 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
17407 ok(!gdi_surface, "Got unexpected surface %p.\n", gdi_surface);
17409 hr = IDirectDraw4_FlipToGDISurface(ddraw);
17410 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
17412 memset(&surface_desc, 0, sizeof(surface_desc));
17413 surface_desc.dwSize = sizeof(surface_desc);
17414 surface_desc.dwFlags = DDSD_CAPS;
17415 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
17416 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
17417 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17419 hr = IDirectDraw4_GetGDISurface(ddraw, &gdi_surface);
17420 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17421 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
17422 IDirectDrawSurface4_Release(gdi_surface);
17424 /* Flipping to the GDI surface requires the primary surface to be
17425 * flippable. */
17426 hr = IDirectDraw4_FlipToGDISurface(ddraw);
17427 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#lx.\n", hr);
17429 IDirectDrawSurface4_Release(primary);
17431 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
17432 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17434 memset(&surface_desc, 0, sizeof(surface_desc));
17435 surface_desc.dwSize = sizeof(surface_desc);
17436 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
17437 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
17438 U5(surface_desc).dwBackBufferCount = 1;
17439 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
17440 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17441 hr = IDirectDrawSurface4_GetAttachedSurface(primary, &caps, &backbuffer);
17442 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17443 ok(backbuffer != primary, "Got unexpected backbuffer %p.\n", backbuffer);
17445 hr = IDirectDraw4_GetGDISurface(ddraw, &gdi_surface);
17446 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17447 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
17448 IDirectDrawSurface4_Release(gdi_surface);
17450 hr = IDirectDrawSurface4_Flip(primary, NULL, DDFLIP_WAIT);
17451 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17452 hr = IDirectDraw4_GetGDISurface(ddraw, &gdi_surface);
17453 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17454 ok(gdi_surface == backbuffer || broken(gdi_surface == primary),
17455 "Got unexpected surface %p, expected %p.\n", gdi_surface, backbuffer);
17456 IDirectDrawSurface4_Release(gdi_surface);
17458 hr = IDirectDraw4_FlipToGDISurface(ddraw);
17459 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17461 hr = IDirectDraw4_GetGDISurface(ddraw, &gdi_surface);
17462 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17463 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
17464 IDirectDrawSurface4_Release(gdi_surface);
17466 hr = IDirectDraw4_FlipToGDISurface(ddraw);
17467 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17469 IDirectDrawSurface4_Release(backbuffer);
17470 IDirectDrawSurface4_Release(primary);
17472 refcount = IDirectDraw4_Release(ddraw);
17473 ok(!refcount, "%lu references left.\n", refcount);
17474 DestroyWindow(window);
17477 static void test_alphatest(void)
17479 #define ALPHATEST_PASSED 0x0000ff00
17480 #define ALPHATEST_FAILED 0x00ff0000
17481 D3DRECT rect_full = {{0}, {0}, {640}, {480}};
17482 IDirect3DViewport3 *viewport;
17483 IDirect3DDevice3 *device;
17484 IDirectDrawSurface4 *rt;
17485 unsigned int color, i;
17486 ULONG refcount;
17487 HWND window;
17488 DWORD value;
17489 HRESULT hr;
17491 static const struct
17493 D3DCMPFUNC func;
17494 unsigned int color_less, color_equal, color_greater;
17496 test_data[] =
17498 {D3DCMP_NEVER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED},
17499 {D3DCMP_LESS, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED},
17500 {D3DCMP_EQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED},
17501 {D3DCMP_LESSEQUAL, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_FAILED},
17502 {D3DCMP_GREATER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_PASSED},
17503 {D3DCMP_NOTEQUAL, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED},
17504 {D3DCMP_GREATEREQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED},
17505 {D3DCMP_ALWAYS, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
17507 static struct
17509 struct vec3 position;
17510 DWORD diffuse;
17512 quad[] =
17514 {{-1.0f, -1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
17515 {{-1.0f, 1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
17516 {{ 1.0f, -1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
17517 {{ 1.0f, 1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
17520 window = create_window();
17521 if (!(device = create_device(window, DDSCL_NORMAL)))
17523 skip("Failed to create a 3D device.\n");
17524 DestroyWindow(window);
17525 return;
17527 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
17528 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17530 viewport = create_viewport(device, 0, 0, 640, 480);
17531 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
17532 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17534 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
17535 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17536 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
17537 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17538 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
17539 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17540 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
17541 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17543 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
17545 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHAFUNC, test_data[i].func);
17546 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17548 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0f, 0);
17549 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17550 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0x70);
17551 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17552 hr = IDirect3DDevice3_BeginScene(device);
17553 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17554 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
17555 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
17556 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17557 hr = IDirect3DDevice3_EndScene(device);
17558 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17559 color = get_surface_color(rt, 320, 240);
17560 ok(compare_color(color, test_data[i].color_greater, 0),
17561 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
17562 color, test_data[i].color_greater, test_data[i].func);
17564 hr = IDirect3DViewport3_Clear2(viewport, 1, &rect_full, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0f, 0);
17565 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17566 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0xff70);
17567 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17568 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHAREF, &value);
17569 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17570 ok(value == 0xff70, "Got unexpected value %#lx.\n", value);
17571 hr = IDirect3DDevice3_BeginScene(device);
17572 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17573 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
17574 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
17575 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17576 hr = IDirect3DDevice3_EndScene(device);
17577 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
17578 color = get_surface_color(rt, 320, 240);
17579 ok(compare_color(color, test_data[i].color_greater, 0),
17580 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
17581 color, test_data[i].color_greater, test_data[i].func);
17584 destroy_viewport(device, viewport);
17585 IDirectDrawSurface4_Release(rt);
17586 refcount = IDirect3DDevice3_Release(device);
17587 ok(!refcount, "Device has %lu references left.\n", refcount);
17588 DestroyWindow(window);
17591 static void test_clipper_refcount(void)
17593 IDirectDrawSurface4 *surface;
17594 IDirectDrawClipper *clipper, *clipper2;
17595 DDSURFACEDESC2 surface_desc;
17596 IDirectDraw4 *ddraw;
17597 IDirectDraw *ddraw1;
17598 ULONG refcount;
17599 HWND window;
17600 HRESULT hr;
17601 BOOL changed;
17602 const IDirectDrawClipperVtbl *orig_vtbl;
17604 window = create_window();
17605 ddraw = create_ddraw();
17606 ok(!!ddraw, "Failed to create a ddraw object.\n");
17607 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
17608 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17610 memset(&surface_desc, 0, sizeof(surface_desc));
17611 surface_desc.dwSize = sizeof(surface_desc);
17612 surface_desc.dwFlags = DDSD_CAPS;
17613 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
17614 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
17615 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17617 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
17618 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
17619 refcount = get_refcount((IUnknown *)clipper);
17620 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
17622 /* Show that clipper validation doesn't somehow happen through per-clipper vtable
17623 * pointers. */
17624 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper2, NULL);
17625 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
17626 ok(clipper->lpVtbl == clipper2->lpVtbl, "Got different clipper vtables %p and %p.\n",
17627 clipper->lpVtbl, clipper2->lpVtbl);
17628 orig_vtbl = clipper->lpVtbl;
17629 IDirectDrawClipper_Release(clipper2);
17631 /* Surfaces hold a reference to clippers. No surprises there. */
17632 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
17633 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
17634 refcount = get_refcount((IUnknown *)clipper);
17635 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
17637 hr = IDirectDrawSurface4_GetClipper(surface, &clipper2);
17638 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#lx.\n", hr);
17639 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
17640 refcount = IDirectDrawClipper_Release(clipper2);
17641 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
17643 hr = IDirectDrawSurface4_SetClipper(surface, NULL);
17644 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
17645 refcount = get_refcount((IUnknown *)clipper);
17646 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
17648 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
17649 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
17650 refcount = get_refcount((IUnknown *)clipper);
17651 ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
17653 refcount = IDirectDrawSurface4_Release(surface);
17654 ok(!refcount, "%lu references left.\n", refcount);
17655 refcount = get_refcount((IUnknown *)clipper);
17656 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
17658 /* SetClipper with an invalid pointer crashes. */
17660 /* Clipper methods work with a broken vtable, with the exception of Release. */
17661 clipper->lpVtbl = (void *)0xdeadbeef;
17662 refcount = orig_vtbl->AddRef(clipper);
17663 todo_wine ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount);
17664 refcount = orig_vtbl->Release(clipper);
17665 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
17667 clipper->lpVtbl = orig_vtbl;
17668 refcount = orig_vtbl->Release(clipper);
17669 todo_wine ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
17671 /* Fix the refcount difference because Wine did not increase the ref in the
17672 * AddRef call above. */
17673 if (refcount)
17675 refcount = IDirectDrawClipper_Release(clipper);
17676 ok(!refcount, "Got unexpected refcount %lu.\n", refcount);
17679 /* Steal the reference and see what happens - releasing the surface works fine.
17680 * The clipper is destroyed and not kept alive by a hidden refcount - trying to
17681 * release it after the GetClipper call is likely to crash, and certain to crash
17682 * if we allocate and zero as much heap memory as we can get. */
17683 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
17684 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17685 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
17686 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#lx.\n", hr);
17687 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
17688 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#lx.\n", hr);
17690 IDirectDrawClipper_Release(clipper);
17691 IDirectDrawClipper_Release(clipper);
17693 if (0)
17695 /* Disabled because it causes heap corruption (HeapValidate fails and random
17696 * hangs in a later HeapFree) on Windows on one of my Machines: MacbookPro 10,1
17697 * running Windows 10 18363.535 and Nvidia driver 425.31. Driver version 441.66
17698 * is affected too. Some testbot machines have crashes directly in GetClipper
17699 * or proceed with a corrupted heap too.
17701 * The same Windows and driver versions run the test without heap corruption on
17702 * a Geforce 1060 GTX card. I have not seen the problem on AMD GPUs either. */
17703 hr = IDirectDrawSurface4_GetClipper(surface, &clipper2);
17704 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#lx.\n", hr);
17705 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
17708 /* Show that invoking the Release method does not crash, but don't get the
17709 * vtable through the clipper pointer because it is no longer pointing to
17710 * valid memory. */
17711 refcount = orig_vtbl->Release(clipper);
17712 ok(!refcount, "%lu references left.\n", refcount);
17714 refcount = IDirectDrawSurface4_Release(surface);
17715 ok(!refcount, "%lu references left.\n", refcount);
17717 /* It looks like the protection against invalid thispointers is part of
17718 * the IDirectDrawClipper method implementation, not IDirectDrawSurface. */
17719 clipper = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x1000);
17720 ok(!!clipper, "failed to allocate memory\n");
17722 /* Assigning the vtable to our fake clipper does NOT make a difference on
17723 * native - there is a different member of the clipper implementation struct
17724 * that is used to determine if a clipper is valid. */
17725 clipper->lpVtbl = orig_vtbl;
17727 refcount = orig_vtbl->AddRef(clipper);
17728 todo_wine ok(!refcount, "Got refcount %lu.\n", refcount);
17729 refcount = orig_vtbl->AddRef((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef);
17730 ok(!refcount, "Got refcount %lu.\n", refcount);
17732 changed = 0x1234;
17733 hr = orig_vtbl->IsClipListChanged(clipper, &changed);
17734 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
17735 todo_wine ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
17737 changed = 0x1234;
17738 hr = orig_vtbl->IsClipListChanged((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef, &changed);
17739 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
17740 ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
17742 /* Nope, we can't initialize our fake clipper. */
17743 hr = IDirectDraw4_QueryInterface(ddraw, &IID_IDirectDraw, (void **)&ddraw1);
17744 ok(SUCCEEDED(hr), "Failed to get ddraw1 interface, hr %#lx.\n", hr);
17746 hr = orig_vtbl->Initialize(clipper, ddraw1, 0);
17747 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#lx.\n", hr);
17749 IDirectDraw_Release(ddraw1);
17751 HeapFree(GetProcessHeap(), 0, clipper);
17753 refcount = IDirectDraw4_Release(ddraw);
17754 ok(!refcount, "%lu references left.\n", refcount);
17755 DestroyWindow(window);
17758 static void test_caps(void)
17760 DWORD caps_never, caps_always, caps_hal;
17761 DDCAPS hal_caps, hel_caps;
17762 IDirectDraw4 *ddraw;
17763 IDirectDraw *ddraw1;
17764 HRESULT hr;
17765 BOOL no3d;
17767 caps_never = DDSCAPS_RESERVED1
17768 | DDSCAPS_ALPHA
17769 | DDSCAPS_PRIMARYSURFACELEFT
17770 | DDSCAPS_SYSTEMMEMORY
17771 | DDSCAPS_VISIBLE
17772 | DDSCAPS_WRITEONLY
17773 | DDSCAPS_LIVEVIDEO
17774 | DDSCAPS_HWCODEC
17775 | DDSCAPS_MODEX
17776 | DDSCAPS_RESERVED2
17777 | 0x01000000u
17778 | 0x02000000u
17779 | DDSCAPS_ALLOCONLOAD
17780 | DDSCAPS_VIDEOPORT
17781 | DDSCAPS_STANDARDVGAMODE
17782 | DDSCAPS_OPTIMIZED;
17784 caps_always = DDSCAPS_FLIP
17785 | DDSCAPS_OFFSCREENPLAIN
17786 | DDSCAPS_PRIMARYSURFACE
17787 | DDSCAPS_TEXTURE
17788 | DDSCAPS_ZBUFFER
17789 | DDSCAPS_MIPMAP;
17791 caps_hal = DDSCAPS_BACKBUFFER
17792 | DDSCAPS_COMPLEX
17793 | DDSCAPS_FRONTBUFFER
17794 | DDSCAPS_3DDEVICE
17795 | DDSCAPS_VIDEOMEMORY
17796 | DDSCAPS_LOCALVIDMEM
17797 | DDSCAPS_NONLOCALVIDMEM;
17799 ddraw = create_ddraw();
17800 ok(!!ddraw, "Failed to create a ddraw object.\n");
17802 memset(&hal_caps, 0, sizeof(hal_caps));
17803 memset(&hel_caps, 0, sizeof(hel_caps));
17804 hal_caps.dwSize = sizeof(hal_caps);
17805 hel_caps.dwSize = sizeof(hel_caps);
17806 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, &hel_caps);
17807 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17808 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
17809 "Got unexpected caps %#lx, expected %#lx.\n",
17810 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
17811 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
17812 "Got unexpected caps %#lx, expected %#lx.\n",
17813 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
17815 no3d = !(hal_caps.ddsCaps.dwCaps & DDSCAPS_3DDEVICE);
17816 if (hal_caps.ddsCaps.dwCaps)
17818 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
17819 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
17820 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
17821 "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
17823 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
17824 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
17825 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
17826 "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
17828 IDirectDraw4_Release(ddraw);
17830 if (hal_caps.ddsCaps.dwCaps)
17832 hr = DirectDrawCreate((GUID *)DDCREATE_HARDWAREONLY, &ddraw1, NULL);
17833 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17834 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw);
17835 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17836 IDirectDraw_Release(ddraw1);
17838 memset(&hal_caps, 0, sizeof(hal_caps));
17839 memset(&hel_caps, 0, sizeof(hel_caps));
17840 hal_caps.dwSize = sizeof(hal_caps);
17841 hel_caps.dwSize = sizeof(hel_caps);
17842 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, &hel_caps);
17843 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17844 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
17845 "Got unexpected caps %#lx, expected %#lx.\n",
17846 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
17847 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
17848 "Got unexpected caps %#lx, expected %#lx.\n",
17849 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
17851 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
17852 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
17853 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
17854 "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
17855 todo_wine ok(!hel_caps.ddsCaps.dwCaps, "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
17857 IDirectDraw4_Release(ddraw);
17860 hr = DirectDrawCreate((GUID *)DDCREATE_EMULATIONONLY, &ddraw1, NULL);
17861 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17862 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw);
17863 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17864 IDirectDraw_Release(ddraw1);
17866 memset(&hal_caps, 0, sizeof(hal_caps));
17867 memset(&hel_caps, 0, sizeof(hel_caps));
17868 hal_caps.dwSize = sizeof(hal_caps);
17869 hel_caps.dwSize = sizeof(hel_caps);
17870 hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, &hel_caps);
17871 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17872 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
17873 "Got unexpected caps %#lx, expected %#lx.\n",
17874 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
17875 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
17876 "Got unexpected caps %#lx, expected %#lx.\n",
17877 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
17879 todo_wine ok(!hal_caps.ddsCaps.dwCaps, "Got unexpected caps %#lx.\n", hal_caps.ddsCaps.dwCaps);
17880 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
17881 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
17882 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
17883 "Got unexpected caps %#lx.\n", hel_caps.ddsCaps.dwCaps);
17885 IDirectDraw4_Release(ddraw);
17888 static void test_d32_support(void)
17890 IDirectDrawSurface4 *surface;
17891 DDSURFACEDESC2 surface_desc;
17892 IDirectDraw4 *ddraw;
17893 ULONG refcount;
17894 HWND window;
17895 HRESULT hr;
17897 window = create_window();
17898 ddraw = create_ddraw();
17899 ok(!!ddraw, "Failed to create a ddraw object.\n");
17900 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
17901 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17903 memset(&surface_desc, 0, sizeof(surface_desc));
17904 surface_desc.dwSize = sizeof(surface_desc);
17905 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
17906 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
17907 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
17908 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
17909 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 32;
17910 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0xffffffff;
17911 surface_desc.dwWidth = 64;
17912 surface_desc.dwHeight = 64;
17913 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
17914 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17916 memset(&surface_desc, 0, sizeof(surface_desc));
17917 surface_desc.dwSize = sizeof(surface_desc);
17918 hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
17919 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
17920 ok((surface_desc.dwFlags & DDSD_PIXELFORMAT), "Got unexpected flags %#lx.\n", surface_desc.dwFlags);
17921 ok(U4(surface_desc).ddpfPixelFormat.dwFlags & DDPF_ZBUFFER,
17922 "Got unexpected format flags %#lx.\n", U4(surface_desc).ddpfPixelFormat.dwFlags);
17923 ok(U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth == 32,
17924 "Got unexpected dwZBufferBitDepth %lu.\n", U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth);
17925 ok(U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask == 0xffffffff,
17926 "Got unexpected Z mask 0x%08lx.\n", U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask);
17927 ok(!(surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY),
17928 "Got unexpected surface caps %#lx.\n", surface_desc.ddsCaps.dwCaps);
17929 IDirectDrawSurface4_Release(surface);
17931 refcount = IDirectDraw4_Release(ddraw);
17932 ok(!refcount, "%lu references left.\n", refcount);
17933 DestroyWindow(window);
17936 static void test_surface_format_conversion_alpha(void)
17938 static const unsigned int rgba_data[4 * 4] =
17940 0xff00ff00, 0xff0000ff, 0xff0000ff, 0xff0000ff,
17941 0xff0000ff, 0xff00ff00, 0xff0000ff, 0xff0000ff,
17942 0xff00ff00, 0xff0000ff, 0xff00ff00, 0xff0000ff,
17943 0xff00ff00, 0xff0000ff, 0xff0000ff, 0xff00ff00,
17945 static const unsigned int rgbx_data[4 * 4] =
17947 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff,
17948 0x000000ff, 0x0000ff00, 0x000000ff, 0x000000ff,
17949 0x0000ff00, 0x000000ff, 0x0000ff00, 0x000000ff,
17950 0x0000ff00, 0x000000ff, 0x000000ff, 0x0000ff00,
17952 static const unsigned short int r5g6b5_data[4 * 4] =
17954 0x07e0, 0x001f, 0x001f, 0x001f,
17955 0x001f, 0x07e0, 0x001f, 0x001f,
17956 0x07e0, 0x001f, 0x07e0, 0x001f,
17957 0x07e0, 0x001f, 0x001f, 0x07e0,
17959 static const unsigned short int r5g5b5x1_data[4 * 4] =
17961 0x03e0, 0x001f, 0x001f, 0x001f,
17962 0x001f, 0x03e0, 0x001f, 0x001f,
17963 0x03e0, 0x001f, 0x03e0, 0x001f,
17964 0x03e0, 0x001f, 0x001f, 0x03e0,
17966 static const unsigned short int r5g5b5a1_data[4 * 4] =
17968 0x83e0, 0x801f, 0x801f, 0x801f,
17969 0x801f, 0x83e0, 0x801f, 0x801f,
17970 0x83e0, 0x801f, 0x83e0, 0x801f,
17971 0x83e0, 0x801f, 0x801f, 0x83e0,
17973 static const unsigned int dxt1_data[8] =
17975 0x001f07e0, 0x14445154,
17977 static const unsigned int dxt2_data[16] =
17979 0xffffffff, 0xffffffff, 0x001f07e0, 0x14445154,
17982 enum test_format_id
17984 FMT_RGBA,
17985 FMT_RGBX,
17986 FMT_R5G6B5,
17987 FMT_R5G5B5X1,
17988 FMT_R5G5B5A1,
17989 FMT_DXT1,
17990 FMT_DXT2,
17991 FMT_DXT3,
17994 static const struct test_format
17996 DDPIXELFORMAT fmt;
17997 const char *name;
17998 unsigned int block_size, x_blocks, y_blocks;
17999 DWORD support_flag;
18000 BOOL broken_software_blit, broken_hardware_blit;
18002 formats[] =
18006 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
18007 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
18009 "RGBA", 4, 4, 4,
18013 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
18014 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
18016 "RGBX", 4, 4, 4,
18020 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
18021 {16}, {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}
18023 "R5G6B5", 2, 4, 4, 0, TRUE,
18024 /* Looks broken for sysmem texture conversions on Windows (at
18025 * least with hardware device), the result is either error from
18026 * _Blt() or a copy of the source data without any conversion. */
18030 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
18031 {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}
18033 "R5G5B5X1", 2, 4, 4,
18037 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
18038 {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}
18040 "R5G5B5A1", 2, 4, 4, 0, FALSE, TRUE,
18044 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
18045 {0}, {0}, {0}, {0}, {0}
18047 "DXT1", 8, 1, 1, SUPPORT_DXT1,
18051 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '2'),
18052 {0}, {0}, {0}, {0}, {0}
18054 "DXT2", 16, 1, 1, SUPPORT_DXT2,
18058 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '3'),
18059 {0}, {0}, {0}, {0}, {0}
18061 "DXT3", 16, 1, 1, SUPPORT_DXT3,
18065 static const struct
18067 DWORD src_caps, dst_caps;
18069 test_caps[] =
18071 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
18072 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
18073 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
18074 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
18077 static const struct
18079 enum test_format_id src_format;
18080 const void *src_data;
18081 enum test_format_id dst_format;
18082 const void *expected_data;
18083 BOOL todo;
18085 tests[] =
18087 #if 0
18088 /* The following 3 tests give different results on AMD and NVIDIA on Windows, disabling. */
18089 {FMT_RGBX, rgbx_data, FMT_RGBA, rgba_data},
18090 {FMT_RGBA, rgba_data, FMT_RGBX, rgbx_data},
18091 {FMT_R5G5B5X1, r5g5b5x1_data, FMT_RGBA, rgba_data},
18092 #endif
18093 {FMT_R5G6B5, r5g6b5_data, FMT_RGBA, rgba_data},
18094 {FMT_R5G6B5, r5g6b5_data, FMT_R5G5B5A1, r5g5b5a1_data},
18095 {FMT_R5G5B5X1, r5g5b5x1_data, FMT_R5G5B5A1, r5g5b5x1_data, TRUE},
18096 {FMT_R5G5B5A1, r5g5b5a1_data, FMT_R5G6B5, r5g6b5_data},
18097 {FMT_RGBA, rgba_data, FMT_DXT1, dxt1_data},
18098 {FMT_RGBX, rgbx_data, FMT_DXT1, dxt1_data},
18099 {FMT_RGBA, rgba_data, FMT_DXT2, dxt2_data},
18100 {FMT_RGBX, rgbx_data, FMT_DXT2, dxt2_data},
18101 {FMT_RGBA, rgba_data, FMT_DXT3, dxt2_data},
18102 {FMT_RGBX, rgbx_data, FMT_DXT3, dxt2_data},
18103 {FMT_DXT1, dxt1_data, FMT_DXT2, dxt2_data},
18104 {FMT_DXT1, dxt1_data, FMT_RGBA, rgba_data},
18105 {FMT_DXT1, dxt1_data, FMT_RGBX, rgba_data},
18106 {FMT_DXT3, dxt2_data, FMT_RGBA, rgba_data},
18107 {FMT_DXT3, dxt2_data, FMT_RGBX, rgba_data},
18110 const struct test_format *src_format, *dst_format;
18111 IDirectDrawSurface4 *src_surf, *dst_surf;
18112 DDSURFACEDESC2 surface_desc, lock;
18113 unsigned int i, j, x, y, pitch;
18114 IDirect3DDevice3 *device;
18115 DWORD supported_fmts;
18116 IDirectDraw4 *ddraw;
18117 ULONG refcount;
18118 BOOL is_wine;
18119 HWND window;
18120 BOOL passed;
18121 HRESULT hr;
18123 window = create_window();
18124 if (!(device = create_device(window, DDSCL_NORMAL)))
18126 skip("Failed to create a 3D device, skipping test.\n");
18127 DestroyWindow(window);
18128 return;
18131 ddraw = create_ddraw();
18132 ok(!!ddraw, "Failed to create a ddraw object.\n");
18133 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
18134 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
18136 hr = IDirect3DDevice3_EnumTextureFormats(device, test_block_formats_creation_cb,
18137 &supported_fmts);
18138 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
18140 is_wine = !strcmp(winetest_platform, "wine");
18142 memset(&surface_desc, 0, sizeof(surface_desc));
18143 surface_desc.dwSize = sizeof(surface_desc);
18144 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
18145 surface_desc.dwWidth = 4;
18146 surface_desc.dwHeight = 4;
18148 for (i = 0; i < ARRAY_SIZE(tests); ++i)
18150 src_format = &formats[tests[i].src_format];
18151 dst_format = &formats[tests[i].dst_format];
18153 if (~supported_fmts & dst_format->support_flag)
18155 skip("%s format is not supported, skipping test %u.\n", dst_format->name, i);
18156 continue;
18158 if (~supported_fmts & src_format->support_flag)
18160 skip("%s format is not supported, skipping test %u.\n", src_format->name, i);
18161 continue;
18164 for (j = 0; j < ARRAY_SIZE(test_caps); ++j)
18166 if (!is_wine && ((test_caps[j].src_caps | test_caps[j].dst_caps) & DDSCAPS_SYSTEMMEMORY)
18167 && (src_format->broken_software_blit || dst_format->broken_software_blit))
18168 continue;
18169 if (!is_wine && (test_caps[j].dst_caps & DDSCAPS_VIDEOMEMORY)
18170 && dst_format->broken_hardware_blit)
18171 continue;
18173 U4(surface_desc).ddpfPixelFormat = src_format->fmt;
18174 surface_desc.ddsCaps.dwCaps = test_caps[j].src_caps;
18175 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surf, NULL);
18176 ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#lx.\n", j, i, hr);
18178 U4(surface_desc).ddpfPixelFormat = dst_format->fmt;
18179 surface_desc.ddsCaps.dwCaps = test_caps[j].dst_caps;
18180 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surf, NULL);
18181 ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#lx.\n", j, i, hr);
18183 memset(&lock, 0, sizeof(lock));
18184 lock.dwSize = sizeof(lock);
18185 hr = IDirectDrawSurface4_Lock(src_surf, NULL, &lock, 0, NULL);
18186 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
18187 pitch = U1(lock).lPitch;
18188 for (y = 0; y < src_format->y_blocks; ++y)
18190 memcpy((BYTE *)lock.lpSurface + y * pitch,
18191 (BYTE *)tests[i].src_data + y * src_format->x_blocks * src_format->block_size,
18192 src_format->block_size * src_format->x_blocks);
18194 hr = IDirectDrawSurface4_Unlock(src_surf, NULL);
18195 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
18197 hr = IDirectDrawSurface4_Blt(dst_surf, NULL, src_surf, NULL, DDBLT_WAIT, NULL);
18198 if (!is_wine && FAILED(hr))
18200 /* Some software blits are rejected on Windows. */
18201 IDirectDrawSurface4_Release(dst_surf);
18202 IDirectDrawSurface4_Release(src_surf);
18203 skip("Skipping test (%u, %u), cannot blit %s -> %s, hr %#lx.\n", j, i,
18204 src_format->name, dst_format->name, hr);
18205 continue;
18207 ok(hr == DD_OK, "Test (%u, %s -> %s), got unexpected hr %#lx.\n", j,
18208 src_format->name, dst_format->name, hr);
18210 memset(&lock, 0, sizeof(lock));
18211 lock.dwSize = sizeof(lock);
18212 hr = IDirectDrawSurface4_Lock(dst_surf, NULL, &lock, 0, NULL);
18213 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
18214 pitch = U1(lock).lPitch;
18216 for (y = 0; y < dst_format->y_blocks; ++y)
18218 const void *expected_data = tests[i].expected_data;
18220 passed = !memcmp((BYTE*)lock.lpSurface + y * pitch,
18221 (BYTE *)expected_data + y * dst_format->x_blocks * dst_format->block_size,
18222 dst_format->block_size * dst_format->x_blocks);
18223 todo_wine_if(tests[i].todo)
18224 ok(passed, "Test (%u, %s -> %s), row %u, unexpected surface data.\n", j,
18225 src_format->name, dst_format->name, y);
18227 if (!passed && !(is_wine && tests[i].todo))
18229 for (x = 0; x < dst_format->x_blocks * dst_format->block_size / 4; ++x)
18231 trace("Test (%u, %u), x %u, y %u, got 0x%08x, expected 0x%08x.\n", j, i, x, y,
18232 *(unsigned int *)((BYTE *)lock.lpSurface + y * pitch + x * 4),
18233 *(unsigned int *)((BYTE *)expected_data + y * dst_format->x_blocks
18234 * dst_format->block_size + x * 4));
18237 if (!passed)
18238 break;
18240 hr = IDirectDrawSurface4_Unlock(dst_surf, NULL);
18241 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
18243 IDirectDrawSurface4_Release(dst_surf);
18244 IDirectDrawSurface4_Release(src_surf);
18248 IDirect3DDevice3_Release(device);
18249 refcount = IDirectDraw4_Release(ddraw);
18250 ok(!refcount, "%lu references left.\n", refcount);
18251 DestroyWindow(window);
18254 struct find_different_mode_param
18256 unsigned int old_width;
18257 unsigned int old_height;
18258 unsigned int old_frequency;
18259 unsigned int new_width;
18260 unsigned int new_height;
18261 unsigned int new_frequency;
18262 unsigned int new_bpp;
18265 static HRESULT CALLBACK find_different_mode_callback(DDSURFACEDESC2 *surface_desc, void *context)
18267 struct find_different_mode_param *param = context;
18269 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
18270 return DDENUMRET_OK;
18272 /* See comment in ddraw7 about the frequency. */
18273 if (surface_desc->dwWidth != param->old_width && surface_desc->dwHeight != param->old_height &&
18274 (!compare_uint(surface_desc->dwRefreshRate, param->old_frequency, 1) || !param->old_frequency))
18276 /* See test_coop_level_mode_set_enum_cb() for why enumeration might accidentally continue. */
18277 if (!param->new_width || (param->new_width < registry_mode.dmPelsWidth
18278 && param->new_height < registry_mode.dmPelsHeight))
18280 param->new_width = surface_desc->dwWidth;
18281 param->new_height = surface_desc->dwHeight;
18282 param->new_frequency = surface_desc->dwRefreshRate;
18283 param->new_bpp = surface_desc->ddpfPixelFormat.dwRGBBitCount;
18285 return DDENUMRET_CANCEL;
18288 return DDENUMRET_OK;
18291 static void test_cursor_clipping(void)
18293 struct find_different_mode_param param;
18294 DDSURFACEDESC2 surface_desc;
18295 RECT rect, clip_rect;
18296 IDirectDraw4 *ddraw;
18297 HWND window;
18298 HRESULT hr;
18299 BOOL ret;
18301 window = create_window();
18302 ok(!!window, "Failed to create a window.\n");
18303 ddraw = create_ddraw();
18304 ok(!!ddraw, "Failed to create a ddraw object.\n");
18306 memset(&surface_desc, 0, sizeof(surface_desc));
18307 surface_desc.dwSize = sizeof(surface_desc);
18308 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
18309 ok(hr == DD_OK, "GetDisplayMode failed, hr %#lx.\n", hr);
18311 memset(&param, 0, sizeof(param));
18312 param.old_width = surface_desc.dwWidth;
18313 param.old_height = surface_desc.dwHeight;
18314 hr = IDirectDraw4_EnumDisplayModes(ddraw, 0, NULL, &param, find_different_mode_callback);
18315 ok(hr == DD_OK, "EnumDisplayModes failed, hr %#lx.\n", hr);
18316 if (!(param.new_width && param.new_height))
18318 skip("Failed to find a different mode than %ux%u.\n", param.old_width, param.old_height);
18319 goto done;
18322 ret = ClipCursor(NULL);
18323 ok(ret, "ClipCursor failed, error %lu.\n", GetLastError());
18324 get_virtual_rect(&rect);
18325 ret = GetClipCursor(&clip_rect);
18326 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
18327 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18328 wine_dbgstr_rect(&clip_rect));
18330 /* Set cooperative level to normal */
18331 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
18332 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
18333 flush_events();
18334 get_virtual_rect(&rect);
18335 ret = GetClipCursor(&clip_rect);
18336 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
18337 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18338 wine_dbgstr_rect(&clip_rect));
18340 hr = set_display_mode(ddraw, param.new_width, param.new_height);
18341 ok(hr == DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode failed, hr %#lx.\n", hr);
18342 if (FAILED(hr))
18344 win_skip("SetDisplayMode failed, hr %#lx.\n", hr);
18345 goto done;
18347 flush_events();
18348 get_virtual_rect(&rect);
18349 ret = GetClipCursor(&clip_rect);
18350 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
18351 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18352 wine_dbgstr_rect(&clip_rect));
18354 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
18355 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#lx.\n", hr);
18356 flush_events();
18357 get_virtual_rect(&rect);
18358 ret = GetClipCursor(&clip_rect);
18359 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
18360 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18361 wine_dbgstr_rect(&clip_rect));
18363 /* Switch to full screen cooperative level */
18364 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
18365 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
18366 flush_events();
18367 SetRect(&rect, 0, 0, param.old_width, param.old_height);
18368 ret = GetClipCursor(&clip_rect);
18369 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
18370 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18371 wine_dbgstr_rect(&clip_rect));
18373 hr = set_display_mode(ddraw, param.new_width, param.new_height);
18374 ok(hr == DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode failed, hr %#lx.\n", hr);
18375 if (FAILED(hr))
18377 win_skip("SetDisplayMode failed, hr %#lx.\n", hr);
18378 goto done;
18380 flush_events();
18381 SetRect(&rect, 0, 0, param.new_width, param.new_height);
18382 ret = GetClipCursor(&clip_rect);
18383 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
18384 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18385 wine_dbgstr_rect(&clip_rect));
18387 /* Restore display mode */
18388 hr = IDirectDraw4_RestoreDisplayMode(ddraw);
18389 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#lx.\n", hr);
18390 flush_events();
18391 SetRect(&rect, 0, 0, param.old_width, param.old_height);
18392 ret = GetClipCursor(&clip_rect);
18393 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
18394 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18395 wine_dbgstr_rect(&clip_rect));
18397 /* Switch to normal cooperative level */
18398 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
18399 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
18400 flush_events();
18401 get_virtual_rect(&rect);
18402 ret = GetClipCursor(&clip_rect);
18403 ok(ret, "GetClipCursor failed, error %lu.\n", GetLastError());
18404 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18405 wine_dbgstr_rect(&clip_rect));
18407 done:
18408 IDirectDraw4_Release(ddraw);
18409 DestroyWindow(window);
18412 static BOOL CALLBACK test_window_position_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect,
18413 LPARAM lparam)
18415 RECT primary_rect, window_rect, new_rect;
18416 IDirectDraw4 *ddraw;
18417 HWND window;
18418 HRESULT hr;
18419 BOOL ret;
18421 ddraw = create_ddraw();
18422 ok(!!ddraw, "Failed to create a ddraw object.\n");
18423 window = CreateWindowA("static", "ddraw_test", WS_POPUP | WS_VISIBLE, monitor_rect->left,
18424 monitor_rect->top, 100, 100, NULL, NULL, NULL, NULL);
18425 ok(!!window, "Failed to create a window.\n");
18426 flush_events();
18428 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
18429 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
18430 flush_events();
18431 ret = GetWindowRect(window, &window_rect);
18432 ok(ret, "GetWindowRect failed, error %lu.\n", GetLastError());
18433 SetRect(&primary_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
18434 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
18435 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
18437 new_rect = window_rect;
18438 --new_rect.right;
18439 --new_rect.bottom;
18441 ret = MoveWindow(window, new_rect.left, new_rect.top, new_rect.right - new_rect.left,
18442 new_rect.bottom - new_rect.top, TRUE);
18443 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
18444 ret = GetWindowRect(window, &window_rect);
18445 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
18446 ok(EqualRect(&window_rect, &new_rect),
18447 "Expected window rect %s, got %s.\n",
18448 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
18449 /* After processing window events window rectangle gets restored. But only once, the size set
18450 * on the second resize remains. */
18451 flush_events();
18452 ret = GetWindowRect(window, &window_rect);
18453 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
18454 /* Both Windows and Wine change the size of the window. On Windows it is exactly the new size but in Wine
18455 * it may get adjusted depending on window manager. */
18456 ok(window_rect.right != monitor_rect->right && window_rect.bottom != monitor_rect->bottom,
18457 "Expected window rect %s, got %s.\n",
18458 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
18460 ret = MoveWindow(window, new_rect.left, new_rect.top, new_rect.right - new_rect.left,
18461 new_rect.bottom - new_rect.top, TRUE);
18462 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
18463 ret = GetWindowRect(window, &window_rect);
18464 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
18465 ok(EqualRect(&window_rect, &new_rect),
18466 "Expected window rect %s, got %s.\n",
18467 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
18468 flush_events();
18469 ret = GetWindowRect(window, &window_rect);
18470 ok(ret, "Got unexpected ret %#x, error %lu.\n", ret, GetLastError());
18471 ok(window_rect.right != monitor_rect->right && window_rect.bottom != monitor_rect->bottom,
18472 "Expected window rect %s, got %s.\n",
18473 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
18475 /* Window activation should restore the window to fit the whole primary monitor */
18476 ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0,
18477 SWP_NOZORDER | SWP_NOSIZE);
18478 ok(ret, "SetWindowPos failed, error %lu.\n", GetLastError());
18479 ret = SetForegroundWindow(GetDesktopWindow());
18480 ok(ret, "Failed to set foreground window.\n");
18481 flush_events();
18482 ret = ShowWindow(window, SW_RESTORE);
18483 ok(ret, "Failed to restore window, error %lu.\n", GetLastError());
18484 flush_events();
18485 ret = SetForegroundWindow(window);
18486 ok(ret, "SetForegroundWindow failed, error %lu.\n", GetLastError());
18487 flush_events();
18488 ret = GetWindowRect(window, &window_rect);
18489 ok(ret, "GetWindowRect failed, error %lu.\n", GetLastError());
18490 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
18491 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
18493 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
18494 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
18495 ret = GetWindowRect(window, &window_rect);
18496 ok(ret, "GetWindowRect failed, error %lu.\n", GetLastError());
18497 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
18498 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
18500 DestroyWindow(window);
18501 IDirectDraw4_Release(ddraw);
18502 return TRUE;
18505 static void test_window_position(void)
18507 EnumDisplayMonitors(NULL, NULL, test_window_position_cb, 0);
18510 static BOOL CALLBACK test_get_display_mode_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect,
18511 LPARAM lparam)
18513 DDSURFACEDESC2 surface_desc;
18514 IDirectDraw4 *ddraw;
18515 HWND window;
18516 HRESULT hr;
18517 BOOL ret;
18519 ddraw = create_ddraw();
18520 ok(!!ddraw, "Failed to create a ddraw object.\n");
18521 window = create_window();
18522 ok(!!window, "Failed to create a window.\n");
18524 /* Test that DirectDraw doesn't use the device window to determine which monitor to use */
18525 ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0,
18526 SWP_NOZORDER | SWP_NOSIZE);
18527 ok(ret, "SetWindowPos failed, error %lu.\n", GetLastError());
18529 surface_desc.dwSize = sizeof(surface_desc);
18530 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
18531 ok(hr == DD_OK, "GetDisplayMode failed, hr %#lx.\n", hr);
18532 ok(surface_desc.dwWidth == GetSystemMetrics(SM_CXSCREEN), "Expect width %d, got %lu.\n",
18533 GetSystemMetrics(SM_CXSCREEN), surface_desc.dwWidth);
18534 ok(surface_desc.dwHeight == GetSystemMetrics(SM_CYSCREEN), "Expect height %d, got %lu.\n",
18535 GetSystemMetrics(SM_CYSCREEN), surface_desc.dwHeight);
18537 DestroyWindow(window);
18538 IDirectDraw4_Release(ddraw);
18539 return TRUE;
18542 static void test_get_display_mode(void)
18544 static const DWORD flags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_REFRESHRATE | DDSD_PIXELFORMAT | DDSD_PITCH;
18545 struct find_different_mode_param param;
18546 DDSURFACEDESC2 surface_desc;
18547 IDirectDraw4 *ddraw;
18548 DEVMODEW devmode;
18549 HWND window;
18550 HRESULT hr;
18551 BOOL ret;
18553 EnumDisplayMonitors(NULL, NULL, test_get_display_mode_cb, 0);
18555 ddraw = create_ddraw();
18556 ok(!!ddraw, "Failed to create a ddraw object.\n");
18557 window = create_window();
18558 ok(!!window, "Failed to create a window.\n");
18560 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
18561 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#lx.\n", hr);
18563 memset(&devmode, 0, sizeof(devmode));
18564 devmode.dmSize = sizeof(devmode);
18565 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
18566 ok(ret, "EnumDisplaySettingsW failed, error %lu.\n", GetLastError());
18568 surface_desc.dwSize = sizeof(surface_desc);
18569 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
18570 ok(hr == DD_OK, "GetDisplayMode failed, hr %#lx.\n", hr);
18571 ok(surface_desc.dwSize == sizeof(surface_desc), "Got dwSize %lu.\n", surface_desc.dwSize);
18572 ok(surface_desc.dwFlags == flags, "Expected dwFlags %#lx, got %#lx.\n", flags,
18573 surface_desc.dwFlags);
18574 ok(surface_desc.dwWidth == devmode.dmPelsWidth, "Expected width %lu, got %lu.\n",
18575 devmode.dmPelsWidth, surface_desc.dwWidth);
18576 ok(surface_desc.dwHeight == devmode.dmPelsHeight, "Expected height %lu, got %lu.\n",
18577 devmode.dmPelsHeight, surface_desc.dwHeight);
18578 ok(surface_desc.dwRefreshRate == devmode.dmDisplayFrequency, "Expected frequency %lu, got %lu.\n",
18579 devmode.dmDisplayFrequency, surface_desc.dwRefreshRate);
18580 ok(surface_desc.ddpfPixelFormat.dwSize == sizeof(surface_desc.ddpfPixelFormat),
18581 "Got ddpfPixelFormat.dwSize %lu.\n", surface_desc.ddpfPixelFormat.dwSize);
18582 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == devmode.dmBitsPerPel,
18583 "Expected ddpfPixelFormat.dwRGBBitCount %lu, got %lu.\n", devmode.dmBitsPerPel,
18584 surface_desc.ddpfPixelFormat.dwRGBBitCount);
18585 ok(surface_desc.lPitch == devmode.dmPelsWidth * devmode.dmBitsPerPel / 8,
18586 "Expected pitch %lu, got %lu.\n", devmode.dmPelsWidth * devmode.dmBitsPerPel / 8,
18587 surface_desc.lPitch);
18589 memset(&param, 0, sizeof(param));
18590 param.old_frequency = surface_desc.dwRefreshRate;
18591 hr = IDirectDraw4_EnumDisplayModes(ddraw, DDEDM_REFRESHRATES, NULL, &param,
18592 find_different_mode_callback);
18593 ok(hr == DD_OK, "EnumDisplayModes failed, hr %#lx.\n", hr);
18594 if (!param.new_frequency)
18596 skip("Failed to find a display mode with a different frequency.\n");
18597 goto done;
18600 hr = IDirectDraw4_SetDisplayMode(ddraw, param.new_width, param.new_height, param.new_bpp,
18601 param.new_frequency, 0);
18602 ok(hr == DD_OK, "SetDisplayMode failed, hr %#lx.\n", hr);
18603 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
18604 ok(hr == DD_OK, "GetDisplayMode failed, hr %#lx.\n", hr);
18605 ok(surface_desc.dwWidth == param.new_width, "Expected width %u, got %lu.\n", param.new_width,
18606 surface_desc.dwWidth);
18607 ok(surface_desc.dwHeight == param.new_height, "Expected height %u, got %lu.\n", param.new_height,
18608 surface_desc.dwHeight);
18609 ok(surface_desc.dwRefreshRate == param.new_frequency, "Expected frequency %u, got %lu.\n",
18610 param.new_frequency, surface_desc.dwRefreshRate);
18611 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == param.new_bpp,
18612 "Expected ddpfPixelFormat.dwRGBBitCount %lu, got %lu.\n", devmode.dmBitsPerPel,
18613 surface_desc.ddpfPixelFormat.dwRGBBitCount);
18615 done:
18616 DestroyWindow(window);
18617 IDirectDraw4_Release(ddraw);
18620 static void run_for_each_device_type(void (*test_func)(const GUID *))
18622 test_func(&IID_IDirect3DHALDevice);
18623 test_func(&IID_IDirect3DRGBDevice);
18626 static void test_texture_wrong_caps(const GUID *device_guid)
18628 static struct
18630 struct vec3 position;
18631 struct vec2 texcoord;
18633 quad[] =
18635 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
18636 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
18637 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
18638 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
18640 static DDPIXELFORMAT fmt =
18642 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
18643 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
18645 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
18646 unsigned int color, expected_color;
18647 IDirectDrawSurface4 *surface, *rt;
18648 IDirect3DViewport3 *viewport;
18649 IDirect3DTexture2 *texture;
18650 IDirect3DDevice3 *device;
18651 IDirectDraw4 *ddraw;
18652 DDSURFACEDESC2 ddsd;
18653 IDirect3D3 *d3d;
18654 ULONG refcount;
18655 HWND window;
18656 HRESULT hr;
18658 window = create_window();
18659 if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid)))
18661 skip("Failed to create a 3D device, skipping test.\n");
18662 DestroyWindow(window);
18663 return;
18665 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
18666 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
18667 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
18668 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
18669 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
18670 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
18672 viewport = create_viewport(device, 0, 0, 640, 480);
18673 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
18674 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
18676 memset(&ddsd, 0, sizeof(ddsd));
18677 ddsd.dwSize = sizeof(ddsd);
18678 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
18679 ddsd.dwHeight = 16;
18680 ddsd.dwWidth = 16;
18681 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
18682 U4(ddsd).ddpfPixelFormat = fmt;
18683 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
18684 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
18685 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
18686 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
18688 fill_surface(surface, 0xff00ff00);
18690 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
18691 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
18693 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
18694 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
18695 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
18696 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
18697 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
18698 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
18699 hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
18701 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
18702 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
18703 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
18704 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
18705 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
18706 hr = IDirect3DDevice3_BeginScene(device);
18707 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
18708 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
18709 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
18710 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
18711 hr = IDirect3DDevice3_EndScene(device);
18712 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
18714 expected_color = is_software_device_type(device_guid) ? 0x0000ff00 : 0x00ffffff;
18715 color = get_surface_color(rt, 320, 240);
18716 ok(color == expected_color, "Got color 0x%08x, expected 0x%08x.\n", color, expected_color);
18718 IDirect3DTexture2_Release(texture);
18719 IDirectDrawSurface4_Release(surface);
18720 IDirectDrawSurface4_Release(rt);
18721 destroy_viewport(device, viewport);
18722 IDirectDraw4_Release(ddraw);
18723 IDirect3D3_Release(d3d);
18724 refcount = IDirect3DDevice3_Release(device);
18725 ok(!refcount, "Device has %lu references left.\n", refcount);
18726 DestroyWindow(window);
18729 static void test_filling_convention(void)
18731 IDirectDrawSurface4 *rt, *backbuffer, *cur, *ds;
18732 static const DWORD colour_bottom = 0x00ffff00;
18733 static const DWORD colour_clear = 0x000000ff;
18734 static const DWORD colour_right = 0x00000000;
18735 static const DWORD colour_left = 0x00ff0000;
18736 static const DWORD colour_top = 0x0000ff00;
18737 unsigned int colour, expected, i, j, x, y;
18738 IDirect3DViewport3 *viewport;
18739 IDirect3DDevice3 *device;
18740 IDirectDraw4 *ddraw;
18741 DDSURFACEDESC2 desc;
18742 IDirect3D3 *d3d;
18743 ULONG refcount;
18744 HWND window;
18745 HRESULT hr;
18746 BOOL todo;
18748 static const unsigned int vp_size = 8;
18749 D3DRECT clear_rect = {{0}, {0}, {vp_size}, {vp_size}};
18751 /* This test data follows the examples in MSDN's
18752 * "Rasterization Rules (Direct3D 9)" article.
18754 * See the d3d9 test for a comment about the eps value. */
18755 static const float eps = 1.0f / 64.0f;
18756 struct
18758 struct vec3 position;
18759 DWORD diffuse;
18761 center_tris[] =
18763 /* left */
18764 {{-2.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_left},
18765 {{-2.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_left},
18766 {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_left},
18768 /* top */
18769 {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_top},
18770 {{-2.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_top},
18771 {{-0.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_top},
18773 /* right */
18774 {{-0.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_right},
18775 {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_right},
18776 {{-0.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_right},
18778 /* bottom */
18779 {{-2.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_bottom},
18780 {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_bottom},
18781 {{-0.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_bottom},
18784 edge_tris[] =
18786 /* left */
18787 {{-2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_left},
18788 {{-2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_left},
18789 {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_left},
18791 /* top */
18792 {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_top},
18793 {{-2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
18794 {{ 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
18796 /* right */
18797 {{ 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_right},
18798 {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_right},
18799 {{ 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_right},
18801 /* bottom */
18802 {{-2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
18803 {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_bottom},
18804 {{ 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
18806 nudge_right_tris[] =
18808 /* left */
18809 {{eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_left},
18810 {{eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_left},
18811 {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_left},
18813 /* top */
18814 {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_top},
18815 {{eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
18816 {{eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
18818 /* right */
18819 {{eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_right},
18820 {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_right},
18821 {{eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_right},
18823 /* bottom */
18824 {{eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
18825 {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_bottom},
18826 {{eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
18828 nudge_left_tris[] =
18830 {{-eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_left},
18831 {{-eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_left},
18832 {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_left},
18834 /* top */
18835 {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_top},
18836 {{-eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
18837 {{-eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
18839 /* right */
18840 {{-eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_right},
18841 {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_right},
18842 {{-eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_right},
18844 /* bottom */
18845 {{-eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
18846 {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_bottom},
18847 {{-eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
18849 nudge_top_tris[] =
18851 /* left */
18852 {{-2.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_left},
18853 {{-2.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_left},
18854 {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_left},
18856 /* top */
18857 {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_top},
18858 {{-2.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_top},
18859 {{ 0.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_top},
18861 /* right */
18862 {{ 0.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_right},
18863 {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_right},
18864 {{ 0.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_right},
18866 /* bottom */
18867 {{-2.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
18868 {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_bottom},
18869 {{ 0.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
18871 nudge_bottom_tris[] =
18873 /* left */
18874 {{-2.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_left},
18875 {{-2.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_left},
18876 {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_left},
18878 /* top */
18879 {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_top},
18880 {{-2.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_top},
18881 {{ 0.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_top},
18883 /* right */
18884 {{ 0.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_right},
18885 {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_right},
18886 {{ 0.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_right},
18888 /* bottom */
18889 {{-2.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
18890 {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_bottom},
18891 {{ 0.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
18894 struct
18896 struct vec4 position;
18897 DWORD diffuse;
18899 center_tris_t[] =
18901 /* left */
18902 {{ 1.5f, 1.5f, 0.0f, 1.0f}, colour_left},
18903 {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_left},
18904 {{ 1.5f, 5.5f, 0.0f, 1.0f}, colour_left},
18906 /* top */
18907 {{ 1.5f, 1.5f, 0.0f, 1.0f}, colour_top},
18908 {{ 3.5f, 1.5f, 0.0f, 1.0f}, colour_top},
18909 {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_top},
18911 /* right */
18912 {{ 3.5f, 1.5f, 0.0f, 1.0f}, colour_right},
18913 {{ 3.5f, 5.5f, 0.0f, 1.0f}, colour_right},
18914 {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_right},
18916 /* bottom */
18917 {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_bottom},
18918 {{ 3.5f, 5.5f, 0.0f, 1.0f}, colour_bottom},
18919 {{ 1.5f, 5.5f, 0.0f, 1.0f}, colour_bottom},
18921 edge_tris_t[] =
18923 /* left */
18924 {{ 2.0f, 1.0f, 0.0f, 1.0f}, colour_left},
18925 {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_left},
18926 {{ 2.0f, 5.0f, 0.0f, 1.0f}, colour_left},
18928 /* top */
18929 {{ 2.0f, 1.0f, 0.0f, 1.0f}, colour_top},
18930 {{ 4.0f, 1.0f, 0.0f, 1.0f}, colour_top},
18931 {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_top},
18933 /* right */
18934 {{ 4.0f, 1.0f, 0.0f, 1.0f}, colour_right},
18935 {{ 4.0f, 5.0f, 0.0f, 1.0f}, colour_right},
18936 {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_right},
18938 /* bottom */
18939 {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_bottom},
18940 {{ 4.0f, 5.0f, 0.0f, 1.0f}, colour_bottom},
18941 {{ 2.0f, 5.0f, 0.0f, 1.0f}, colour_bottom},
18944 const struct
18946 void *geometry;
18947 DWORD fvf;
18948 const char *expected[8];
18950 tests[] =
18953 center_tris,
18954 D3DFVF_XYZ | D3DFVF_DIFFUSE,
18956 " ",
18957 " ",
18958 " TT ",
18959 " LR ",
18960 " LR ",
18961 " BB ",
18962 " ",
18967 edge_tris,
18968 D3DFVF_XYZ | D3DFVF_DIFFUSE,
18970 " ",
18971 " TT ",
18972 " LT ",
18973 " LR ",
18974 " LB ",
18975 " ",
18976 " ",
18981 nudge_right_tris,
18982 D3DFVF_XYZ | D3DFVF_DIFFUSE,
18984 " ",
18985 " TT ",
18986 " TR ",
18987 " LR ",
18988 " BR ",
18989 " ",
18990 " ",
18995 nudge_left_tris,
18996 D3DFVF_XYZ | D3DFVF_DIFFUSE,
18998 " ",
18999 " TT ",
19000 " LT ",
19001 " LR ",
19002 " LB ",
19003 " ",
19004 " ",
19009 nudge_top_tris,
19010 D3DFVF_XYZ | D3DFVF_DIFFUSE,
19012 " ",
19013 " LT ",
19014 " LT ",
19015 " LB ",
19016 " LB ",
19017 " ",
19018 " ",
19023 nudge_bottom_tris,
19024 D3DFVF_XYZ | D3DFVF_DIFFUSE,
19026 " ",
19027 " ",
19028 " LT ",
19029 " Lt ",
19030 " LB ",
19031 " lB ",
19032 " ",
19037 center_tris_t,
19038 D3DFVF_XYZRHW | D3DFVF_DIFFUSE,
19040 " ",
19041 " ",
19042 " TT ",
19043 " LR ",
19044 " LR ",
19045 " BB ",
19046 " ",
19051 edge_tris_t,
19052 D3DFVF_XYZRHW | D3DFVF_DIFFUSE,
19054 " ",
19055 " TT ",
19056 " LT ",
19057 " LR ",
19058 " LB ",
19059 " ",
19060 " ",
19066 window = create_window();
19067 if (!(device = create_device(window, DDSCL_NORMAL)))
19069 skip("Failed to create 3D device.\n");
19070 DestroyWindow(window);
19071 return;
19074 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
19075 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
19076 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
19077 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
19078 hr = IDirect3DDevice3_GetRenderTarget(device, &backbuffer);
19079 ok(hr == DD_OK, "Got unexpected hr %#lx.\n", hr);
19080 viewport = create_viewport(device, 0, 0, vp_size, vp_size);
19081 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
19082 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
19084 memset(&desc, 0, sizeof(desc));
19085 desc.dwSize = sizeof(desc);
19086 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
19087 desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
19088 desc.dwWidth = vp_size;
19089 desc.dwHeight = vp_size;
19090 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
19091 desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
19092 desc.ddpfPixelFormat.dwRGBBitCount = 32;
19093 desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
19094 desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
19095 desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
19096 hr = IDirectDraw4_CreateSurface(ddraw, &desc, &rt, NULL);
19097 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
19099 /* Nvidia on Windows 10 refuses to set the offscreen RT
19100 * if it does not have an attached depth stencil. */
19101 ds = get_depth_stencil(device);
19102 memset(&desc, 0, sizeof(desc));
19103 desc.dwSize = sizeof(desc);
19104 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
19105 hr = IDirectDrawSurface4_GetPixelFormat(ds, &desc.ddpfPixelFormat);
19106 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
19107 IDirectDrawSurface4_Release(ds);
19109 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
19110 desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
19111 desc.dwWidth = vp_size;
19112 desc.dwHeight = vp_size;
19113 hr = IDirectDraw4_CreateSurface(ddraw, &desc, &ds, NULL);
19114 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
19115 hr = IDirectDrawSurface4_AddAttachedSurface(rt, ds);
19116 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#lx.\n", hr);
19118 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
19119 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
19120 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
19121 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
19123 for (i = 0; i < ARRAY_SIZE(tests); ++i)
19125 for (j = 0; j < 2; ++j)
19127 cur = j ? rt : backbuffer;
19129 hr = IDirect3DDevice3_SetRenderTarget(device, cur, 0);
19130 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
19131 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, colour_clear, 0.0f, 0);
19132 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
19134 hr = IDirect3DDevice3_BeginScene(device);
19135 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
19136 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLELIST,
19137 tests[i].fvf, tests[i].geometry, 12, 0);
19138 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
19139 hr = IDirect3DDevice3_EndScene(device);
19140 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
19142 for (y = 0; y < 8; y++)
19144 for (x = 0; x < 8; x++)
19146 todo = FALSE;
19147 switch (tests[i].expected[y][x])
19149 case 'l': todo = TRUE;
19150 case 'L':
19151 expected = colour_left;
19152 break;
19153 case 't': todo = TRUE;
19154 case 'T':
19155 expected = colour_top;
19156 break;
19157 case 'r': todo = TRUE;
19158 case 'R':
19159 expected = colour_right;
19160 break;
19161 case 'b': todo = TRUE;
19162 case 'B':
19163 expected = colour_bottom;
19164 break;
19165 case ' ':
19166 expected = colour_clear;
19167 break;
19168 default:
19169 ok(0, "Unexpected entry in expected test char\n");
19170 expected = 0xdeadbeef;
19172 colour = get_surface_color(cur, x, y);
19173 /* The nudge-to-bottom test fails on cards that give us a bottom-left
19174 * filling convention. The cause isn't the bottom part of the filling
19175 * convention, but because wined3d will nudge geometry to the left to
19176 * keep diagonals (the 'R' in test case 'edge_tris') intact. */
19177 todo_wine_if(todo && !compare_color(colour, expected, 1))
19178 ok(compare_color(colour, expected, 1), "Got unexpected colour %08x, %ux%u, case %u, j %u.\n",
19179 colour, x, y, i, j);
19185 destroy_viewport(device, viewport);
19186 IDirectDrawSurface4_Release(backbuffer);
19187 IDirectDrawSurface4_Release(rt);
19188 IDirectDrawSurface4_Release(ds);
19189 IDirectDraw4_Release(ddraw);
19190 IDirect3D3_Release(d3d);
19191 refcount = IDirect3DDevice3_Release(device);
19192 ok(!refcount, "Device has %lu references left.\n", refcount);
19193 DestroyWindow(window);
19196 static HRESULT WINAPI test_enum_devices_caps_callback(GUID *guid, char *device_desc,
19197 char *device_name, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, void *ctx)
19199 if(IsEqualGUID(&IID_IDirect3DRGBDevice, guid))
19201 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
19202 "RGB Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n");
19203 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
19204 "RGB Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n");
19205 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
19206 "RGB Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
19207 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
19208 "RGB Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
19210 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
19211 "RGB Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
19212 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
19213 "RGB Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
19214 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
19215 "RGB Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
19216 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
19217 "RGB Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
19219 ok(hal->dcmColorModel == 0, "RGB Device hal caps has colormodel %lu\n", hal->dcmColorModel);
19220 ok(hel->dcmColorModel == D3DCOLOR_RGB, "RGB Device hel caps has colormodel %lu\n", hel->dcmColorModel);
19222 ok(hal->dwFlags == 0, "RGB Device hal caps has hardware flags %#lx\n", hal->dwFlags);
19223 ok(hel->dwFlags != 0, "RGB Device hel caps has hardware flags %#lx\n", hel->dwFlags);
19225 ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
19226 "RGB Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
19227 ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
19228 "RGB Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
19229 ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
19230 "RGB Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
19231 ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
19232 "RGB Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
19234 else if(IsEqualGUID(&IID_IDirect3DHALDevice, guid))
19236 ok(hal->dcmColorModel == D3DCOLOR_RGB, "HAL Device hal caps has colormodel %lu\n", hel->dcmColorModel);
19237 ok(hel->dcmColorModel == 0, "HAL Device hel caps has colormodel %lu\n", hel->dcmColorModel);
19239 ok(hal->dwFlags != 0, "HAL Device hal caps has hardware flags %#lx\n", hal->dwFlags);
19240 ok(hel->dwFlags != 0, "HAL Device hel caps has hardware flags %#lx\n", hel->dwFlags);
19242 ok(hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT,
19243 "HAL Device hal device caps does not have D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
19244 ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
19245 "RGB Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
19246 ok(hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX,
19247 "HAL Device hal device caps does not have D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
19248 ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
19249 "RGB Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
19251 else if(IsEqualGUID(&IID_IDirect3DRefDevice, guid))
19253 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
19254 "REF Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n");
19255 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
19256 "REF Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n");
19257 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
19258 "REF Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
19259 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
19260 "REF Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
19262 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
19263 "REF Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
19264 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
19265 "REF Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
19266 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
19267 "REF Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
19268 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
19269 "REF Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
19271 ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
19272 "REF Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
19273 ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
19274 "REF Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
19275 ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
19276 "REF Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
19277 ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
19278 "REF Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
19280 else if(IsEqualGUID(&IID_IDirect3DRampDevice, guid))
19282 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
19283 "Ramp Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n");
19284 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
19285 "Ramp Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n");
19286 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
19287 "Ramp Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
19288 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
19289 "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
19291 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
19292 "Ramp Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
19293 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
19294 "Ramp Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
19295 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
19296 "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
19297 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
19298 "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
19300 ok(hal->dcmColorModel == 0, "Ramp Device hal caps has colormodel %lu\n", hal->dcmColorModel);
19301 ok(hel->dcmColorModel == D3DCOLOR_MONO, "Ramp Device hel caps has colormodel %lu\n",
19302 hel->dcmColorModel);
19304 ok(hal->dwFlags == 0, "Ramp Device hal caps has hardware flags %#lx\n", hal->dwFlags);
19305 ok(hel->dwFlags != 0, "Ramp Device hel caps has hardware flags %#lx\n", hel->dwFlags);
19307 ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
19308 "Ramp Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
19309 ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
19310 "Ramp Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
19311 ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
19312 "Ramp Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
19313 ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
19314 "Ramp Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
19316 else if(IsEqualGUID(&IID_IDirect3DMMXDevice, guid))
19318 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
19319 "MMX Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n");
19320 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
19321 "MMX Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n");
19322 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
19323 "MMX Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
19324 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
19325 "MMX Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n");
19327 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
19328 "MMX Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
19329 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
19330 "MMX Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n");
19331 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
19332 "MMX Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
19333 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
19334 "MMX Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n");
19336 ok(hal->dcmColorModel == 0, "MMX Device hal caps has colormodel %lu\n", hal->dcmColorModel);
19337 ok(hel->dcmColorModel == D3DCOLOR_RGB, "MMX Device hel caps has colormodel %lu\n", hel->dcmColorModel);
19339 ok(hal->dwFlags == 0, "MMX Device hal caps has hardware flags %#lx\n", hal->dwFlags);
19340 ok(hel->dwFlags != 0, "MMX Device hel caps has hardware flags %#lx\n", hel->dwFlags);
19342 ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
19343 "MMX Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
19344 ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0,
19345 "MMX Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n");
19346 ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
19347 "MMX Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
19348 ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0,
19349 "MMX Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n");
19351 else
19353 ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", device_desc, device_name);
19354 if (hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)
19355 trace("hal line has pow2 set\n");
19356 else
19357 trace("hal line does NOT have pow2 set\n");
19358 if (hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)
19359 trace("hal tri has pow2 set\n");
19360 else
19361 trace("hal tri does NOT have pow2 set\n");
19362 if (hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)
19363 trace("hel line has pow2 set\n");
19364 else
19365 trace("hel line does NOT have pow2 set\n");
19366 if (hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2)
19367 trace("hel tri has pow2 set\n");
19368 else
19369 trace("hel tri does NOT have pow2 set\n");
19372 return DDENUMRET_OK;
19375 static void test_enum_devices(void)
19377 IDirectDraw4 *ddraw;
19378 IDirect3D3 *d3d;
19379 ULONG refcount;
19380 HRESULT hr;
19382 ddraw = create_ddraw();
19383 ok(!!ddraw, "Failed to create a ddraw object.\n");
19385 hr = IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d);
19386 if (FAILED(hr))
19388 skip("D3D interface is not available, skipping test.\n");
19389 IDirectDraw4_Release(ddraw);
19390 return;
19393 hr = IDirect3D3_EnumDevices(d3d, NULL, NULL);
19394 ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr);
19396 hr = IDirect3D3_EnumDevices(d3d, test_enum_devices_caps_callback, NULL);
19397 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
19399 IDirect3D3_Release(d3d);
19400 refcount = IDirectDraw4_Release(ddraw);
19401 ok(!refcount, "Device has %lu references left.\n", refcount);
19404 START_TEST(ddraw4)
19406 DDDEVICEIDENTIFIER identifier;
19407 DEVMODEW current_mode;
19408 IDirectDraw4 *ddraw;
19409 HMODULE dwmapi;
19411 if (!(ddraw = create_ddraw()))
19413 skip("Failed to create a ddraw object, skipping tests.\n");
19414 return;
19417 if (ddraw_get_identifier(ddraw, &identifier))
19419 trace("Driver string: \"%s\"\n", identifier.szDriver);
19420 trace("Description string: \"%s\"\n", identifier.szDescription);
19421 trace("Driver version %d.%d.%d.%d\n",
19422 HIWORD(U(identifier.liDriverVersion).HighPart), LOWORD(U(identifier.liDriverVersion).HighPart),
19423 HIWORD(U(identifier.liDriverVersion).LowPart), LOWORD(U(identifier.liDriverVersion).LowPart));
19425 IDirectDraw4_Release(ddraw);
19427 memset(&current_mode, 0, sizeof(current_mode));
19428 current_mode.dmSize = sizeof(current_mode);
19429 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
19430 registry_mode.dmSize = sizeof(registry_mode);
19431 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
19432 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
19433 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
19435 skip("Current mode does not match registry mode, skipping test.\n");
19436 return;
19439 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
19440 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
19442 test_process_vertices();
19443 test_coop_level_create_device_window();
19444 test_clipper_blt();
19445 test_coop_level_d3d_state();
19446 test_surface_interface_mismatch();
19447 test_coop_level_threaded();
19448 run_for_each_device_type(test_depth_blit);
19449 test_texture_load_ckey();
19450 test_viewport_object();
19451 run_for_each_device_type(test_zenable);
19452 run_for_each_device_type(test_ck_rgba);
19453 test_ck_default();
19454 test_ck_complex();
19455 test_surface_qi();
19456 test_device_qi();
19457 test_wndproc();
19458 test_window_style();
19459 test_redundant_mode_set();
19460 test_coop_level_mode_set();
19461 test_coop_level_mode_set_multi();
19462 test_initialize();
19463 test_coop_level_surf_create();
19464 test_vb_discard();
19465 test_coop_level_multi_window();
19466 test_draw_strided();
19467 test_lighting();
19468 test_specular_lighting();
19469 test_clear_rect_count();
19470 test_coop_level_versions();
19471 test_lighting_interface_versions();
19472 test_coop_level_activateapp();
19473 test_texturemanage();
19474 test_block_formats_creation();
19475 test_unsupported_formats();
19476 run_for_each_device_type(test_rt_caps);
19477 test_primary_caps();
19478 test_surface_lock();
19479 test_surface_discard();
19480 test_flip();
19481 test_set_surface_desc();
19482 test_user_memory_getdc();
19483 test_sysmem_overlay();
19484 test_primary_palette();
19485 test_surface_attachment();
19486 test_private_data();
19487 test_pixel_format();
19488 test_create_surface_pitch();
19489 test_mipmap();
19490 test_palette_complex();
19491 test_p8_blit();
19492 test_material();
19493 test_palette_gdi();
19494 test_palette_alpha();
19495 test_vb_writeonly();
19496 test_lost_device();
19497 test_surface_desc_lock();
19498 test_texturemapblend();
19499 test_signed_formats();
19500 test_color_fill();
19501 test_texcoordindex();
19502 test_colorkey_precision();
19503 test_range_colorkey();
19504 test_shademode();
19505 test_lockrect_invalid();
19506 test_yv12_overlay();
19507 test_offscreen_overlay();
19508 test_overlay_rect();
19509 test_blt();
19510 test_blt_z_alpha();
19511 test_cross_device_blt();
19512 test_color_clamping();
19513 test_getdc();
19514 test_draw_primitive();
19515 test_edge_antialiasing_blending();
19516 test_transform_vertices();
19517 test_display_mode_surface_pixel_format();
19518 test_surface_desc_size();
19519 test_get_surface_from_dc();
19520 test_ck_operation();
19521 test_vb_refcount();
19522 test_compute_sphere_visibility();
19523 test_texture_stages_limits();
19524 test_set_render_state();
19525 test_map_synchronisation();
19526 test_depth_readback();
19527 test_clear();
19528 test_enum_surfaces();
19529 test_viewport();
19530 test_find_device();
19531 test_killfocus();
19532 test_sysmem_draw();
19533 test_gdi_surface();
19534 test_alphatest();
19535 test_clipper_refcount();
19536 test_caps();
19537 test_d32_support();
19538 test_surface_format_conversion_alpha();
19539 test_cursor_clipping();
19540 test_window_position();
19541 test_get_display_mode();
19542 run_for_each_device_type(test_texture_wrong_caps);
19543 test_filling_convention();
19544 test_enum_devices();